1    /*
     2     * Copyright (c) 2015-2018, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     *
    32    /*
    33     *  ======== HeapTrack.xdc ========
    34     *
    35     */
    36    package ti.sysbios.heaps;
    37    
    38    import xdc.runtime.Memory;
    39    import xdc.runtime.IHeap;
    40    import ti.sysbios.knl.Task;
    41    import ti.sysbios.knl.Queue;
    42    import xdc.rov.ViewInfo;
    43    
    44    /*!
    45     *  ======== HeapTrack ========
    46     *  Heap manager that enables tracking of all allocated blocks.
    47     *
    48     *  HeapTrack manager provides functions to allocate and free storage from a
    49     *  configured heap which inherits from IHeap. The calling context is going to
    50     *  match the heap being used.
    51     *
    52     *  HeapTrack is useful for detecting memory leaks, double frees and buffer
    53     *  overflows.  There is a performance overhead cost when using heap track as
    54     *  well as a size impact. Every alloc will include a {@link #Tracker}
    55     *  structure (plus memory to get proper alignment of the stucture) at
    56     *  the end of the buffer that should not be modified by the user. It is
    57     *  important to remember this when deciding on heap sizes and you may have to
    58     *  adjust the total size or buffer sizes (for HeapBuf/HeapMultiBuf).
    59     *
    60     *  ROV displays peaks and current in-use for both allocated memory (requested
    61     *  size + Tracker structure) and requested memory (without Tracker).
    62     *
    63     *  The information stored in the tracker packet is used to display information
    64     *  in RTOS Object Viewer (ROV) as well as with the printTask and printHeap
    65     *  functions.
    66     *
    67     *  The asserts used in this module are listed below and include error checking
    68     *  for double frees, calling printHeap with a null handle, buffer overflows
    69     *  and deleting a non empty heap.
    70     */
    71    
    72    @InstanceFinalize  /* Destroys the trackQueue Q */
    73    
    74    module HeapTrack inherits xdc.runtime.IHeap {
    75    
    76        /*!
    77         *  ======== BasicView ========
    78         *  @_nodoc
    79         */
    80        metaonly struct BasicView {
    81            IHeap.Handle heapHandle;
    82            String inUse;
    83            String inUsePeak;
    84            String inUseWithoutTracker;
    85            String inUsePeakWithoutTracker;
    86        }
    87    
    88        /*!
    89         *  ======== TaskView ========
    90         *  @_nodoc
    91         */
    92        metaonly struct TaskView {
    93            String block;
    94            String heapHandle;
    95            String blockAddr;
    96            String requestedSize;
    97            String clockTick;
    98            String overflow;
    99        }
   100    
   101        /*!
   102         *  ======== HeapListView ========
   103         *  @_nodoc
   104         */
   105        metaonly struct HeapListView {
   106            String block;
   107            String taskHandle;
   108            String heapHandle;
   109            String blockAddr;
   110            String requestedSize;
   111            String clockTick;
   112            String overflow;
   113        }
   114    
   115        /*! @_nodoc */
   116        @Facet
   117        metaonly config ViewInfo.Instance rovViewInfo =
   118            ViewInfo.create({
   119                viewMap: [
   120                    ['Basic',    {type: ViewInfo.INSTANCE, viewInitFxn:
   121                    'viewInitBasic', structName: 'BasicView'}],
   122                    ['HeapAllocList', {type: ViewInfo.INSTANCE_DATA, viewInitFxn:
   123                    'viewInitHeapList',  structName: 'HeapListView'}],
   124                    ['TaskAllocList',     {type: ViewInfo.TREE_TABLE, viewInitFxn:
   125                    'viewInitTask',  structName: 'TaskView'}],
   126                ]
   127            });
   128    
   129        /*!
   130         *  ======== Tracker ========
   131         *  Structure added to the end of each allocated block
   132         *
   133         *  When a block is allocated from a HeapTrack heap with a size,
   134         *  internally HeapTrack calls Memory_alloc on the configured
   135         *  {@link #heap}. The value of sizeof(HeapTrack_Tracker)
   136         *  is added to the requested size.
   137         *
   138         *  For example, if the caller makes the following call (where heapHandle
   139         *  is an HeapTrack handle that has been converted to an IHeap_Handle).
   140         *  @p(code)
   141         *  buf = Memory_alloc(heapHandle, MYSIZE, MYALIGN, &eb);
   142         *  @p
   143         *
   144         *  Internally, HeapTrack will make the following call
   145         *  (where size is MYSIZE, align is MYALIGN and obj is the HeapTrack handle).
   146         *  @p(code)
   147         *  block = Memory_alloc(obj->heap, size + sizeof(HeapTrack_Tracker), align, &eb);
   148         *  @p
   149         *
   150         *  When using HeapTrack, depending on the  actual heap
   151         *  (i.e. {@link #heap}), you might need to make adjustments to the heap
   152         *  (e.g. increase the blockSize if using a HeapBuf instance).
   153         *
   154         *  The HeapTrack module manages the contents of this structure and should
   155         *  not be directly accessing them.
   156         */
   157        struct Tracker {
   158            UArg scribble;
   159            Queue.Elem queElem;
   160            SizeT size;
   161            UInt32 tick;
   162            Task.Handle taskHandle;
   163        }
   164    
   165        /*!
   166         *  ======== STARTSCRIBBLE ========
   167         *  @_nodoc
   168         *  Constant used to help detect over-writing of a buffer
   169         */
   170        const UArg STARTSCRIBBLE = 0xa5a5a5a5;
   171    
   172        /*!
   173         *  ======== printTask ========
   174         *  Print out the blocks that are currently allocated by a task
   175         *
   176         *  Iterates through all instances of HeapTrack and prints out information
   177         *  about all allocated blocks of memory for a given task handle. This
   178         *  function is not thread safe.
   179         *
   180         *  @params(taskHandle)  Task to print stats for
   181         */
   182        Void printTask(Task.Handle taskHandle);
   183    
   184        /*!
   185         *  ======== A_doubleFree ========
   186         *  Assert raised when freeing a buffer that was already freed
   187         */
   188        config xdc.runtime.Assert.Id A_doubleFree =
   189                {msg: "A_doubleFree: Buffer already free"};
   190    
   191        /*!
   192         *  ======== A_bufOverflow ========
   193         *  Assert raised when freeing memory with corrupted data or using the
   194         *  wrong size
   195         */
   196        config xdc.runtime.Assert.Id A_bufOverflow =
   197                {msg: "A_bufOverflow: Buffer overflow"};
   198    
   199        /*!
   200         *  ======== A_notEmpty ========
   201         *  Assert raised when deleting a non-empty heap
   202         */
   203        config xdc.runtime.Assert.Id A_notEmpty =
   204            {msg: "A_notEmpty: Heap not empty"};
   205    
   206    
   207        /*!
   208         *  ======== A_nullObject ========
   209         *  Assert raised when calling printTask with a null HeapTrack object
   210         */
   211        config xdc.runtime.Assert.Id A_nullObject =
   212                {msg: "A_nullObject: HeapTrack_printHeap called with null obj"};
   213    
   214    instance:
   215    
   216        /*!
   217         *  ======== internalHeap ========
   218         *  Heap to use with HeapTrack
   219         */
   220        config IHeap.Handle heap = null;
   221    
   222        /*!
   223         *  ======== printHeap ========
   224         *  Print details for a HeapTrack instance
   225         *
   226         *  Print the details of all allocated blocks of memory for a HeapTrack
   227         *  instance.  This function is not thread safe.
   228         */
   229        Void printHeap();
   230    
   231    internal:
   232    
   233        /*
   234         *  ======== NOSCRIBBLE ========
   235         *  Using a non-zero constant in the free to aid in the development
   236         *  of this module.
   237         */
   238        const UArg NOSCRIBBLE = 0x05101920;
   239    
   240        /*
   241         *  ======== printTrack ========
   242         *  Returns FALSE if a corrupted scribble is found.
   243         */
   244        Bool printTrack(Tracker *tracker, Handle handle);
   245    
   246        /* instance object */
   247        struct Instance_State {
   248            IHeap.Handle                internalHeap;
   249            ti.sysbios.knl.Queue.Object trackQueue;
   250            SizeT                       size;
   251            SizeT                       peak;
   252            SizeT                       sizeWithoutTracker;
   253            SizeT                       peakWithoutTracker;
   254        };
   255    }