1    /*
     2     * Copyright (c) 2013, 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     *  ======== HeapBuf.xdc ========
    34     *
    35     */
    36    
    37    package ti.sysbios.heaps;
    38    
    39    import xdc.rov.ViewInfo;
    40    
    41    /*!
    42     *  ======== HeapBuf ========
    43     *  Fixed size buffer heap manager
    44     *
    45     *  The HeapBuf manager provides functions to allocate and free storage from a
    46     *  heap of type HeapBuf which inherits from IHeap. HeapBuf manages a single
    47     *  fixed-size buffer, split into equally sized allocable blocks.
    48     *
    49     *  The HeapBuf manager is intended as a very fast and deterministic memory
    50     *  manager which can only allocate blocks of a single size. It is ideal for
    51     *  managing a heap that is only used for allocating a single type of object,
    52     *  or for objects that have very similar sizes.
    53     *
    54     *  Allocation from and freeing to a HeapBuf instance is non-blocking and
    55     *  deterministic: a call to alloc or free will always take the same amount of
    56     *  time.
    57     *
    58     *  Constraints:
    59     *  @p(blist)
    60     *  - Align parameter must be set to 0 for default, or be a power of 2 that is
    61     *    greater than or equal to the value returned by
    62     *    {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
    63     *  - The buffer passed to dynamically create a HeapBuf must be aligned
    64     *    according to the alignment parameter, and must be large enough to account
    65     *    for the actual block size after it has been rounded up to a multiple of
    66     *    the alignment.
    67     *  @p
    68     *
    69     *  @p(html)
    70     *  <h3> Calling Context </h3>
    71     *  <table border="1" cellpadding="3">
    72     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
    73     *    </colgroup>
    74     *
    75     *    <tr><th> Function    </th><th>  Hwi   </th><th>  Swi   </th>
    76     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    77     *    <!--                                       -->
    78     *    <tr><td> Params_init      </td><td>   Y    </td><td>   Y    </td>
    79     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
    80     *    <tr><td> alloc            </td><td>   Y    </td><td>   Y    </td>
    81     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    82     *    <tr><td> construct        </td><td>   Y    </td><td>   Y    </td>
    83     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    84     *    <tr><td> create           </td><td>   N*   </td><td>   N*   </td>
    85     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    86     *    <tr><td> delete           </td><td>   N*   </td><td>   N*   </td>
    87     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    88     *    <tr><td> destruct         </td><td>   Y    </td><td>   Y    </td>
    89     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    90     *    <tr><td> free             </td><td>   Y    </td><td>   Y    </td>
    91     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    92     *    <tr><td> getStats         </td><td>   Y    </td><td>   Y    </td>
    93     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    94     *    <tr><td> getExtendedStats </td><td>   Y    </td><td>   Y    </td>
    95     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    96     *    <tr><td> isBlocking       </td><td>   Y    </td><td>   Y    </td>
    97     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    98     *    <tr><td colspan="6"> Definitions: <br />
    99     *       <ul>
   100     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   101     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   102     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   103     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   104     *           <ul>
   105     *             <li> In your module startup after this module is started
   106     *    (e.g. HeapBuf_Module_startupDone() returns TRUE). </li>
   107     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   108     *             <li> During main().</li>
   109     *             <li> During BIOS.startupFxns.</li>
   110     *           </ul>
   111     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   112     *           <ul>
   113     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   114     *             <li> In your module startup before this module is started
   115     *    (e.g. HeapBuf_Module_startupDone() returns FALSE).</li>
   116     *           </ul>
   117     *       </ul>
   118     *       <li> <b>*</b>:  Assuming blocking Heap is used for creation. </li>
   119     *    </td></tr>
   120     *
   121     *  </table>
   122     *  @p
   123     */
   124    
   125    @InstanceInitError /* Initialization may throw errors */
   126    @ModuleStartup     /* Instances require more initialization at startup */
   127    @InstanceFinalize  /* Destroys the freeList Q */
   128    
   129    module HeapBuf inherits xdc.runtime.IHeap {
   130    
   131        /*!
   132         *  ======== BasicView ========
   133         *  @_nodoc
   134         */
   135        metaonly struct BasicView {
   136            String    label;
   137            xdc.runtime.Memory.Size bufSize;    /* Size of the entire buffer */
   138            SizeT     blockSize;
   139            UInt      numBlocks;
   140            Int       totalFreeSize;
   141            UInt      numberAllocatedBlocks;
   142            UInt      numFreeBlocks;
   143            UInt      maxAllocatedBlocks;
   144            Ptr       buf;
   145    
   146            /* statStr contains "quick" info 4 HeapBuf that other mods will
   147             * display. statStr won't be displayed by the HeapBuf ROV view itself.
   148             */
   149            String    statStr;
   150        }
   151    
   152        /*!
   153         *  ======== DetailedView ========
   154         *  @_nodoc
   155         */
   156        metaonly struct DetailedView {
   157            String    label;
   158            xdc.runtime.Memory.Size bufSize;    /* Size of the entire buffer */
   159            SizeT     blockSize;
   160            UInt      numBlocks;
   161            Int       totalFreeSize;
   162            UInt      numberAllocatedBlocks;
   163            UInt      numFreeBlocks;
   164            UInt      maxAllocatedBlocks;
   165            Ptr       buf;
   166            Ptr       freeList;
   167    
   168            /* statStr contains "quick" info 4 HeapBuf that other mods will
   169             * display. statStr won't be displayed by the HeapBuf ROV view itself.
   170             */
   171            String    statStr;
   172        }
   173    
   174        /*! @_nodoc */
   175        @Facet
   176        metaonly config ViewInfo.Instance rovViewInfo =
   177            ViewInfo.create({
   178                viewMap: [
   179                        ['Basic',    {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitInstance', structName: 'BasicView'}],
   180                        ['Detailed', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitDetailed', structName: 'DetailedView'}]
   181                ]
   182            });
   183    
   184        /*!
   185         *  ======== ExtendedStats ========
   186         *  Stat structure for the HeapBuf_getExtendedStats function
   187         *
   188         *  @field(maxAllocatedBlocks) The maximum number of blocks allocated from
   189         *                             this heap at any single point in time, during
   190         *                             the lifetime of this HeapBuf instance.
   191         *                             The configuration parameter
   192         *                             {@link #trackMaxAllocs} must be set to true
   193         *                             for this field to have any meaning.
   194         *                             Otherwise, this field will be set to '0'.
   195         *
   196         *  @field(numAllocatedBlocks) The total number of blocks currently
   197         *                             allocated in this HeapBuf instance.
   198         */
   199        struct ExtendedStats {
   200            UInt maxAllocatedBlocks;
   201            UInt numAllocatedBlocks;
   202        }
   203    
   204        /*!
   205         *  ======== A_nullBuf ========
   206         *  Null buf parameter
   207         *
   208         *  This Assert is raised when the buf parameter has been omitted (null)
   209         *  for a dynamic create.
   210         */
   211        config xdc.runtime.Assert.Id A_nullBuf =
   212            {msg: "buf parameter cannot be null"};
   213    
   214        /*!
   215         *  ======== A_bufAlign ========
   216         *  Misalligned buffer
   217         *
   218         *  This Assert is raised when the buf parameter has not been aligned
   219         *  on the requested alignment.
   220         */
   221        config xdc.runtime.Assert.Id A_bufAlign =
   222            {msg: "buf not properly aligned"};
   223    
   224        /*!
   225         *  ======== A_invalidAlign ========
   226         *  Invalid alignment
   227         *
   228         *  This Assert is raised when the align parameter is not the default
   229         *  value of zero, or a power of 2 that is greater than or equal to
   230         *  the value defined by
   231         *  {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
   232         */
   233        config xdc.runtime.Assert.Id A_invalidAlign =
   234            {msg: "align parameter must be 0 or a power of 2 >= the value of Memory_getMaxDefaultTypeAlign()"};
   235    
   236        /*!
   237         *  ======== A_invalidRequestedAlign ========
   238         *  Invalid alignment parameter in the alloc
   239         *
   240         *  This Assert is raised when the align argument is not a power of 2 (or 0).
   241         *  It is also raised if the parameter is greater the alignment
   242         *  specified when creating the heap.
   243         */
   244        config xdc.runtime.Assert.Id A_invalidRequestedAlign =
   245            {msg: "align parameter 1) must be 0 or a power of 2 and 2) not greater than the heaps alignment"};/*!
   246    
   247         *  ======== A_zeroBlockSize ========
   248         *  Assert raised when the blockSize parameter is 0
   249         */
   250        config xdc.runtime.Assert.Id A_zeroBlockSize =
   251            {msg: "blockSize cannot be zero"};
   252    
   253        /*!
   254         *  ======== A_zeroBlocks ========
   255         *  Assert raised when the numBlocks parameter is 0
   256         */
   257        config xdc.runtime.Assert.Id A_zeroBlocks =
   258            {msg: "numBlocks cannot be zero"};
   259    
   260        /*!
   261         *  ======== A_zeroBufSize ========
   262         *  Assert raised when the bufSize parameter is 0
   263         */
   264        config xdc.runtime.Assert.Id A_zeroBufSize =
   265            {msg: "bufSize cannot be zero"};
   266    
   267        /*!
   268         *  ======== A_invalidBufSize ========
   269         *  Invalid buffer size
   270         *
   271         *  This Assert is raised when the bufSize parameter is too small
   272         *  to handle requested blocks.
   273         */
   274        config xdc.runtime.Assert.Id A_invalidBufSize =
   275            {msg: "HeapBuf_create's bufSize parameter is invalid (too small)"};
   276    
   277        /*!
   278         *  ======== A_noBlocksToFree ========
   279         *  No allocated blocks
   280         *
   281         *  This Assert is raised when free is called and there are no blocks
   282         *  allocated.
   283         */
   284        config xdc.runtime.Assert.Id A_noBlocksToFree =
   285            {msg: "Cannot call HeapBuf_free when no blocks have been allocated"};
   286    
   287        /*!
   288         *  ======== A_invalidFree ========
   289         *  Assert raised when an invalid free occurs
   290         *
   291         *  This assert can be caused for the following reasons
   292         *  @p(blist)
   293         *  - Passing a NULL pointer to the free.
   294         *  - The block is not within the heap's buffer range. This can occur if
   295         *    the block is freed to the wrong heap.
   296         *  - The block is not on the proper boundary. This can occur if the
   297         *    pointer returned from alloc is changed by the application and not set
   298         *    back to its original value when free is called.
   299         *  @p
   300         */
   301        config xdc.runtime.Assert.Id A_invalidFree =
   302            {msg: "A_invalidFree: Invalid free"};
   303    
   304        /*!
   305         *  ======== E_size ========
   306         *  Raised when requested size exceeds blockSize
   307         */
   308        config xdc.runtime.Error.Id E_size =
   309            {msg: "requested size is too big: handle=0x%x, size=%u"};
   310    
   311        /*!
   312         *  ======== trackMaxAllocs ========
   313         *  Track maximum number of allocations
   314         *
   315         *  This will enable/disable the tracking of the maximum number of
   316         *  allocations for a HeapBuf instance.  This maximum refers to the "all
   317         *  time" maximum number of allocations for the history of a HeapBuf
   318         *  instance, not the current number of allocations.
   319         */
   320        config Bool trackMaxAllocs = false;
   321    
   322    instance:
   323    
   324        /*!
   325         *  ======== align ========
   326         *  Alignment (in MAUs) of each block
   327         *
   328         *  The alignment must be a power of 2 that is greater than or equal to
   329         *  the target dependent value defined by
   330         *  {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}. If the default value
   331         *  of 0 is specified, this value will be changed to be the minimum
   332         *  structure alignment requirement, as defined by
   333         *  {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
   334         *
   335         *  For static creates, the HeapBuf module will allocate space for the
   336         *  buffer and will align it on this requested alignment.
   337         *
   338         *  For dynamic creates, this parameter is used solely for error checking.
   339         *  The buffer provided to a dynamically created HeapBuf must be aligned
   340         *  manually, and an assert will be raised if the buffer is not properly
   341         *  aligned. For dynamic creates, HeapBuf will NOT adjust the buffer to
   342         *  satisfy the alignment.
   343         *
   344         */
   345        config SizeT align = 0;
   346    
   347        /*!
   348         *  ======== sectionName ========
   349         *  Section name for the buffer managed by the instance
   350         *
   351         *  The buffer allocated for a statically created HeapBuf instance will be
   352         *  placed in this section.
   353         *
   354         *  The default section is the 'dataSection' in the platform.
   355         */
   356        metaonly config String sectionName = null;
   357    
   358        /*!
   359         *  ======== numBlocks ========
   360         *  Number of fixed-size blocks
   361         *
   362         *  Required parameter.
   363         *
   364         *  The default number of blocks is 0.
   365         */
   366        config UInt numBlocks = 0;
   367    
   368        /*!
   369         *  ======== blockSize ========
   370         *  Size (in MAUs) of each block
   371         *
   372         *  HeapBuf will round the blockSize up to the nearest multiple of the
   373         *  alignment, so the actual blockSize may be larger. When creating a
   374         *  HeapBuf dynamically, this needs to be taken into account to determine
   375         *  the proper buffer size to pass in.
   376         *
   377         *  Required parameter.
   378         *
   379         *  The default size of the blocks is 0 MAUs.
   380         */
   381        config SizeT blockSize = 0;
   382    
   383        /*!
   384         *  ======== bufSize ========
   385         *  Size (in MAUs) of the entire buffer; for dynamic creates only
   386         *
   387         *  When dynamically creating a HeapBuf, this should be the actual size
   388         *  of the memory buffer provided for HeapBuf to manage.
   389         *
   390         *  This parameter is used solely for error checking; an Error is raised
   391         *  if the bufSize is too small for the requested blockSize and numBlocks.
   392         *  Because of minimum alignment considerations, it's easy to provide too
   393         *  small of a buffer to manage, and difficult to detect if it happened.
   394         *
   395         *  This parameter is required for dynamic creates and ignored for static
   396         *  creates.
   397         *
   398         *  The default buffer size is 0 MAUs.
   399         */
   400        config xdc.runtime.Memory.Size bufSize = 0;
   401    
   402        /*!
   403         *  ======== buf ========
   404         *  User supplied buffer; for dynamic creates only
   405         *
   406         *  The caller must supply the memory buffer for a dynamically created
   407         *  HeapBuf to manage. The provided buffer must be aligned according to the
   408         *  HeapBuf's alignment parameter. i.e., if a buffer's alignment parameter
   409         *  is 128, then the buffer's start address must be a multiple of 128.
   410         *
   411         *  For static creates, the buffer is allocated automatically based on the
   412         *  blockSize and numBlocks parameters.
   413         *
   414         *  This parameter is required for dynamic creates and ignored for static
   415         *  creates.
   416         *
   417         */
   418        config Ptr buf = 0;
   419    
   420        /*!
   421         *  ======== alloc ========
   422         *  @HeapBuf All alignment is handled in the create, therefore the
   423         *  align argument in alloc is ignored.
   424         *
   425         *  HeapBuf_alloc will only fail if there are no available blocks or if the
   426         *  requested block size is larger than the HeapBuf's blockSize. All other
   427         *  requests, regardless of size, will succeed.
   428         */
   429        override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
   430    
   431        /*!
   432         *  ======== isBlocking ========
   433         *  @HeapBuf This function always returns FALSE since the alloc/free
   434         *  never block on a resource.
   435         */
   436        override Bool isBlocking();
   437    
   438        /*!
   439         *  ======== getBlockSize ========
   440         *  @_nodoc
   441         *  Returns the HeapBuf's actual blockSize (adjusted for alignment)
   442         *
   443         *  This getter is provided to allow other memory managers to build off
   444         *  of HeapBuf.
   445         *
   446         *  The blockSize returned has been adjusted to match the alignment,
   447         *  so it may be larger than the user-specified blockSize.
   448         */
   449        SizeT getBlockSize();
   450    
   451        /*!
   452         *  ======== getAlign ========
   453         *  @_nodoc
   454         *  Returns the HeapBuf's actual alignment (adjusted for minimum
   455         *  alignment requirements)
   456         *
   457         *  This getter is provided to allow other memory managers to build off
   458         *  of HeapBuf.
   459         */
   460        SizeT getAlign();
   461    
   462        /*!
   463         *  ======== getEndAddr ========
   464         *  @_nodoc
   465         *  Returns the last address in the buffer managed by the HeapBuf
   466         *
   467         *  This getter is provided to allow other memory managers to build off
   468         *  of HeapBuf:  Compare a block's address to the end address of the buffer
   469         *  to determine which buffer the block came from. The end address is the
   470         *  last address in the buffer, not the next address after the buffer.
   471         *
   472         *  This will not return the correct value after addMemory has been called
   473         *  to add a noncontiguous buffer of memory to the HeapBuf.
   474         *
   475         */
   476        Ptr getEndAddr();
   477    
   478        /*! ======== getExtendedStats ========
   479         *  Retrieves the extended statistics for a HeapBuf instance.
   480         *
   481         *  This function retrieves the extended statistics for a HeapBuf instance.
   482         *  It does not retrieve the standard xdc.runtime.Memory.Stats information.
   483         *
   484         *  @param(stats)  Location for the returned extended statistics.
   485         */
   486        Void getExtendedStats(ExtendedStats *stats);
   487    
   488        /*!
   489         *  ======== mergeHeapBufs ========
   490         *  @_nodoc
   491         */
   492        Void mergeHeapBufs(HeapBuf.Handle heapBuf2);
   493    
   494    internal:   /* not for client use */
   495    
   496        /*!
   497         *  ======== numConstructedHeaps ========
   498         *  @_nodoc
   499         *  Number of statically constructed Heap objects.
   500         *  Shouldn't be set directly by the user's
   501         *  config (it gets set by instance$static$init).
   502         */
   503        config UInt numConstructedHeaps = 0;
   504    
   505        /*
   506         *  ======== postInit ========
   507         *  finish initializing static and dynamic HeapBufs
   508         */
   509        Void postInit(Object *heap);
   510    
   511        /*
   512         *  ======== Instance_State ========
   513         *  Instance state
   514         */
   515        struct Instance_State {
   516            SizeT        blockSize;             /* True size of each block       */
   517            SizeT        align;                 /* Alignment of each block       */
   518            UInt         numBlocks;             /* Number of individual blocks.  */
   519            xdc.runtime.Memory.Size bufSize;    /* Size of the entire buffer     */
   520            Char         buf[];                 /* Memory managed by instance    */
   521            ti.sysbios.knl.Queue.Object freeList;  /* List of free buffers      */
   522            UInt         numFreeBlocks;
   523            UInt         minFreeBlocks;         /* used to compute max # allocs  */
   524        };
   525    
   526        /*
   527         *  ======== Module_State ========
   528         *  Module state
   529         */
   530        struct Module_State {
   531            Handle  constructedHeaps[];         /* array of statically */
   532                                                /* constructed Heaps */
   533        };
   534    }