1    /* 
     2     * Copyright (c) 2012, 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     *  ======== HeapMem.xdc ========
    34     *
    35     */
    36    
    37    package ti.sysbios.heaps;
    38    
    39    import xdc.rov.ViewInfo;
    40    import xdc.runtime.Memory;
    41    import xdc.runtime.Error;
    42    
    43    /*!
    44     *  ======== HeapMem ========
    45     *  Variable size buffer heap manager
    46     *
    47     *  HeapMem manager provides functions to allocate and free storage from a
    48     *  heap of type HeapMem which inherits from IHeap.
    49     *
    50     *  @p(html)
    51     *  <h3> HeapMem Gate </h3>
    52     *  A HeapMem instance will use the HeapMem module Gate to protect any accesses
    53     *  to its list of free memory blocks. The HeapMem instance will enter and
    54     *  leave the module Gate when allocating blocks, freeing blocks, and
    55     *  retrieving statistics about the HeapMem.
    56     *
    57     *  By default, the Gate is of type GateMutex.
    58     *
    59     *  A different Gate can be specified using the common$.gate parameter.
    60     *  For example, to use a GateTask to protect HeapMem:
    61     *      HeapMem.common$.gate = GateTask.create();
    62     *
    63     *  To save on overhead, HeapMem does not create additional Gate instances on a
    64     *  per-instance basis; there is only one Gate instance shared across all of
    65     *  the HeapMem instances. Therefore, the HeapMem.common$.gateParams parameter
    66     *  (used for configuring per-instance Gates) is ignored.
    67     *
    68     *  The type of Gate used should be chosen based on the type of threads (Hwi,
    69     *  Swi, Task, etc.) using the heap. It should also consider the
    70     *  non-deterministic nature of the HeapMem. A call to alloc or free will
    71     *  traverse a list of free blocks, so a GateHwi, for example, is likely an
    72     *  inappropriate Gate for HeapMem.
    73     *
    74     *  @p(html)
    75     *  <h3> Calling Context </h3>
    76     *  <table border="1" cellpadding="3">
    77     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
    78     *    </colgroup>
    79     *
    80     *    <tr><th> Function    </th><th>  Hwi   </th><th>  Swi   </th>
    81     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    82     *    <!--                                     -->
    83     *    <tr><td> Params_init         </td><td>   Y    </td><td>   Y    </td>
    84     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
    85     *    <tr><td> alloc               </td><td>   N**  </td><td>   N**  </td>
    86     *    <td>   Y**  </td><td>   Y    </td><td>   N    </td></tr>
    87     *    <tr><td> construct           </td><td>   Y    </td><td>   Y    </td>
    88     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    89     *    <tr><td> create              </td><td>   N*   </td><td>   N*   </td>
    90     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    91     *    <tr><td> delete              </td><td>   N*   </td><td>   N*   </td>
    92     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    93     *    <tr><td> destruct            </td><td>   Y    </td><td>   Y    </td>
    94     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    95     *    <tr><td> free                </td><td>   N**  </td><td>   N**  </td>
    96     *    <td>   Y**  </td><td>   Y    </td><td>   N    </td></tr>
    97     *    <tr><td> getExtendedStats    </td><td>   Y    </td><td>   Y    </td>
    98     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    99     *    <tr><td> getStats            </td><td>   N**  </td><td>   N**  </td>
   100     *    <td>   Y**  </td><td>   Y    </td><td>   N    </td></tr>
   101     *    <tr><td> isBlocking          </td><td>   Y    </td><td>   Y    </td>
   102     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   103     *    <tr><td> restore             </td><td>   Y+   </td><td>   Y+   </td>
   104     *    <td>   Y+   </td><td>   Y    </td><td>   N    </td></tr>
   105     *    <tr><td colspan="6"> Definitions: <br />
   106     *       <ul>
   107     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   108     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   109     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   110     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   111     *           <ul>
   112     *             <li> In your module startup after this module is started
   113     *    (e.g. HeapMem_Module_startupDone() returns TRUE). </li>
   114     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   115     *             <li> During main().</li>
   116     *             <li> During BIOS.startupFxns.</li>
   117     *           </ul>
   118     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   119     *           <ul>
   120     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   121     *             <li> In your module startup before this module is started
   122     *    (e.g. HeapMem_Module_startupDone() returns FALSE).</li>
   123     *           </ul>
   124     *       <li> <b>*</b> : Assuming blocking Heap is used for creation. </li>
   125     *       <li> <b>**</b>: Assuming GateMutex is used as HeapMem's Gate. </li>
   126     *       <li> <b>+</b> : Cannot use HeapMem object while it is being
   127     *    restored. </li>
   128     *       </ul>
   129     *    </td></tr>
   130     *
   131     *  </table>
   132     *  @p
   133     */
   134    @Gated
   135    module HeapMem inherits xdc.runtime.IHeap {
   136    
   137        /*! @_nodoc */
   138        @XmlDtd
   139        metaonly struct BasicView {
   140            String            label;
   141            Ptr               buf;
   142            String            sectionName;
   143        }
   144    
   145        /*! @_nodoc */
   146        @XmlDtd
   147        metaonly struct DetailedView {
   148            String            label;
   149            Ptr               buf;
   150            String            sectionName;
   151            Memory.Size       totalSize;
   152            Memory.Size       totalFreeSize;
   153            Memory.Size       largestFreeSize;
   154        }
   155    
   156        /*!
   157         *  ======== FreeBlockView ========
   158         *  @_nodoc
   159         */
   160        metaonly struct FreeBlockView {
   161            String         Address;
   162            String         size;
   163            String         status;
   164        }
   165    
   166        /*! @_nodoc */
   167        @Facet
   168        metaonly config ViewInfo.Instance rovViewInfo =
   169            ViewInfo.create({
   170                viewMap: [
   171                [
   172                    'Basic',
   173                    {
   174                        type: ViewInfo.INSTANCE,
   175                        viewInitFxn: 'viewInitBasic',
   176                        structName: 'BasicView'
   177                    }
   178                ],
   179                [
   180                    'Detailed',
   181                    {
   182                        type: ViewInfo.INSTANCE,
   183                        viewInitFxn: 'viewInitDetailed',
   184                        structName: 'DetailedView'
   185                    }
   186                ],
   187                [
   188                    'FreeList',
   189                    {
   190                        type: ViewInfo.INSTANCE_DATA,
   191                        viewInitFxn: 'viewInitData',
   192                        structName: 'FreeBlockView'
   193                    }
   194                ]
   195                ]
   196            });
   197    
   198    
   199        /*!
   200         *  ======== ExtendedStats ========
   201         *  Stat structure for the HeapMem_getExtendedStats function
   202         *
   203         *  @field(buf)           Base address of the internal buffer.
   204         *                        This may be different from the original buf
   205         *                        parameter due to alignment requirements.
   206         *  @field(size)          Size of the internal buffer.
   207         *                        This may be different from the original size
   208         *                        parameter due to alignment requirements.
   209         */
   210        struct ExtendedStats {
   211            Ptr   buf;
   212            SizeT size;
   213        }
   214    
   215        /*!
   216         *  ======== A_zeroBlock ========
   217         *  Assert raised when a block of size 0 is requested
   218         *
   219         *  This error can also be raised if the requested size wraps
   220         *  the contents of a SizeT type when it is adjusted for a minimum 
   221         *  alignment. For example, when SizeT is 16-bits and a size request
   222         *  is made for 0xFFFB.
   223         */
   224        config xdc.runtime.Assert.Id A_zeroBlock =
   225            {msg: "A_zeroBlock: Cannot allocate size 0"};
   226    
   227        /*!
   228         *  ======== A_heapSize ========
   229         *  Assert raised when the requested heap size is too small
   230         */
   231        config xdc.runtime.Assert.Id A_heapSize =
   232            {msg: "A_heapSize: Requested heap size is too small"};
   233    
   234        /*!
   235         *  ======== A_align ========
   236         *  Assert raised when the requested alignment is not a power of 2
   237         */
   238        config xdc.runtime.Assert.Id A_align =
   239            {msg: "A_align: Requested align is not a power of 2"};
   240    
   241        /*!
   242         *  ======== E_memory ========
   243         *  Raised when requested size exceeds largest free block
   244         */
   245        config Error.Id E_memory = {msg: "out of memory: handle=0x%x, size=%u"};
   246    
   247        /*!
   248         *  ======== A_invalidFree ========
   249         *  Assert raised when the free detects that an invalid addr or size
   250         *
   251         *  This could arise when multiple frees are done on the same buffer or
   252         *  if corruption occurred.
   253         *
   254         *  This also could occur when an alloc is made with size N and the
   255         *  free for this buffer specifies size M where M > N. Note: not every
   256         *  case is detectable.
   257         *
   258         *  This assert can also be caused when passing an invalid addr to free
   259         *  or if the size is causing the end of the buffer to be
   260         *  out of the expected range.
   261         */
   262        config xdc.runtime.Assert.Id A_invalidFree =
   263            {msg: "A_invalidFree: Invalid free"};
   264    
   265        /*!
   266         *  ======== enter ========
   267         *  @_nodoc
   268         *  Enter the module's gate. This is needed to support
   269         *  the legacy MEM module. It allows MEM to use the same
   270         *  gate for thread-safety.
   271         */
   272        @DirectCall
   273        IArg enter();
   274    
   275        /*!
   276         *  ======== leave ========
   277         *  @_nodoc
   278         *  Leave the module's gate. This is needed to support
   279         *  the legacy MEM module. It allows MEM to use the same
   280         *  gate for thread-safety.
   281         */
   282        @DirectCall
   283        Void leave(IArg key);
   284    
   285    instance:
   286    
   287       /*!
   288        *  ======== align ========
   289        *  Alignment of the buffer being managed by this heap instance
   290        *
   291        *  In the static HeapMem.create() call, the buffer allocated for the
   292        *  HeapMem instance will have the alignment specified by this parameter.
   293        *
   294        *  In the dynamic case, the client must supply the buffer, so it is the
   295        *  client's responsibility to manage the buffer's alignment, and there is
   296        *  no 'align' parameter.
   297        *
   298        *  The specified alignment must be a power of 2.
   299        *
   300        *  HeapMem requires that the buffer be aligned on a target-specific minimum
   301        *  alignment, and will adjust (round up) the requested alignment as
   302        *  necessary to satisfy this requirement.
   303        *
   304        *  The default alignment is 0.
   305        */
   306       metaonly config SizeT align = 0;
   307    
   308       /*!
   309        *  ======== sectionName ========
   310        *  Section name for the buffer managed by the instance
   311        *
   312        *  The default section is the 'dataSection' in the platform.
   313        */
   314       metaonly config String sectionName = null;
   315    
   316       /*!
   317        *  ======== buf ========
   318        *  Buffer being managed by this heap instance
   319        *
   320        *  This parameter is ignored in the static HeapMem.create() call. It is a
   321        *  required parameter in the dynamic HeapMem_create() call.
   322        *
   323        *  HeapMem requires that the buffer be aligned on a target-specific minimum
   324        *  alignment, and will adjust the buffer's start address and size as
   325        *  necessary to satisfy this requirement.
   326        */
   327       config Ptr buf = 0;
   328    
   329       /*!
   330        *  ======== size ========
   331        *  Size of buffer being managed by this heap instance
   332        *
   333        *  The usable size may be smaller depending on alignment requirements.
   334        */
   335       config Memory.Size size = 0;
   336    
   337        /*!
   338         *  ======== alloc ========
   339         *
   340         *  @HeapMem
   341         *  The actual block returned may be larger than requested to satisfy
   342         *  alignment requirements
   343         *
   344         *  HeapMem_alloc() will lock the heap using the HeapMem Gate while it
   345         *  traverses the list of free blocks to find a large enough block for
   346         *  the request.
   347         *
   348         *  Guidelines for using large heaps and multiple alloc() calls.
   349         *  @p(blist)
   350         *          - If possible, allocate larger blocks first. Previous
   351         *            allocations of small memory blocks can reduce the size
   352         *            of the blocks available for larger memory allocations.
   353         *          - Realize that alloc() can fail even if the heap contains a
   354         *            sufficient absolute amount of unallocated space. This is
   355         *            because the largest free memory block may be smaller than
   356         *            total amount of unallocated memory.
   357         *  @p
   358         */
   359        @DirectCall
   360        override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
   361    
   362        /*!
   363         *  ======== free ========
   364         *
   365         *  @HeapMem
   366         *  free() places the memory block specified by addr and size back into the
   367         *  free pool of the heap specified. The newly freed block is combined with
   368         *  any adjacent free blocks. The space is then available for further
   369         *  allocation by alloc().
   370         *
   371         *  free() will lock the heap using the HeapMem Gate, if one is specified
   372         *  using 'HeapMem.common$.gate'.
   373         */
   374        @DirectCall
   375        override Void free(Ptr block, SizeT size);
   376    
   377        /*!
   378         *  ======== isBlocking ========
   379         *
   380         *  @HeapMem
   381         *  This function queries the gate (as specified by 'HeapMem.common$.gate')
   382         *  to determine if the alloc/free can be blocking.
   383         */
   384        @DirectCall
   385        override Bool isBlocking();
   386    
   387        /*!
   388         *  ======== getStats ========
   389         *
   390         *  @HeapMem
   391         *  getStats() will lock the heap using the HeapMem Gate while it retrieves
   392         *  the HeapMem's statistics.
   393         *
   394         *  The returned totalSize reflects the usable size of the buffer, not
   395         *  necessarily the size specified during create.
   396         */
   397        @DirectCall
   398        override Void getStats(xdc.runtime.Memory.Stats *stats);
   399    
   400    
   401        /*!
   402         *  ======== restore ========
   403         *  Restores an instance to its original created state
   404         *
   405         *  This function restores a static or dynamically created instance to
   406         *  its original created state. Any memory previously allocated from the
   407         *  heap is no longer valid after this API is called. This function
   408         *  does not check whether there is allocated memory or not.
   409         */
   410        @DirectCall
   411        Void restore();
   412    
   413        /*!
   414         *  ======== getExtendedStats ========
   415         *  Retrieves the extended statistics for a HeapMem instance
   416         *
   417         *  This function retrieves the extended statistics for a HeapMem instance.
   418         *  It does not retrieve the standard xdc.runtime.Memory.Stats information.
   419         *
   420         *  @param(stats)  Location for the returned extended statistics.
   421         */
   422        @DirectCall
   423        Void getExtendedStats(ExtendedStats *stats);
   424    
   425    internal:   /* not for client use */
   426    
   427        /*! 
   428         *  ======== init ========
   429         *  Initialize instance at runtime
   430         *
   431         *  This function is plugged as a Startup.firstFxn so that the
   432         *  HeapMem objects are ready and usable by malloc() and 
   433         *  Memory_alloc() by the time the module startup functions
   434         *  get called so that any calls to atexit(), which in some targets
   435         *  invokes malloc(), will be handled cleanly.
   436         */
   437        Void init();
   438    
   439        /* Required alignment. Must be a power of 2 */
   440        config Int reqAlign;
   441    
   442        /* Required alignment mask. reqAlign - 1 */
   443        config Int reqAlignMask;
   444    
   445        /* Header maintained at the lower address of every free block */
   446        struct Header {
   447            Header *next;
   448            Memory.Size size;
   449        };
   450    
   451        struct Instance_State {
   452            xdc.runtime.Memory.Size align;
   453            Char                    buf[];      /* The heap used by HeapMem. */
   454            Header                  head;       /* First free block pointer.
   455                                                 * The size field will be used
   456                                                 * to store original heap size.
   457                                                 */
   458        };
   459    }
   460    
   461    /*
   462     *  @(#) ti.sysbios.heaps; 2, 0, 0, 0,542; 2-24-2012 11:40:52; /db/vtree/library/trees/avala/avala-q28x/src/ xlibrary
   463    
   464     */
   465