1    /*
     2     * Copyright (c) 2015, 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        /*!
   248         *  ======== A_invalidBlockSize ========
   249         *  Assert raised when the blockSize parameter is not large enough to
   250         *  hold two pointers.
   251         */
   252        config xdc.runtime.Assert.Id A_invalidBlockSize =
   253            {msg: "blockSize must be large enough to hold atleast two pointers"};
   254    
   255        /*!
   256         *  ======== A_zeroBlocks ========
   257         *  Assert raised when the numBlocks parameter is 0
   258         */
   259        config xdc.runtime.Assert.Id A_zeroBlocks =
   260            {msg: "numBlocks cannot be zero"};
   261    
   262        /*!
   263         *  ======== A_zeroBufSize ========
   264         *  Assert raised when the bufSize parameter is 0
   265         */
   266        config xdc.runtime.Assert.Id A_zeroBufSize =
   267            {msg: "bufSize cannot be zero"};
   268    
   269        /*!
   270         *  ======== A_invalidBufSize ========
   271         *  Invalid buffer size
   272         *
   273         *  This Assert is raised when the bufSize parameter is too small
   274         *  to handle requested blocks.
   275         */
   276        config xdc.runtime.Assert.Id A_invalidBufSize =
   277            {msg: "HeapBuf_create's bufSize parameter is invalid (too small)"};
   278    
   279        /*!
   280         *  ======== A_noBlocksToFree ========
   281         *  No allocated blocks
   282         *
   283         *  This Assert is raised when free is called and there are no blocks
   284         *  allocated.
   285         */
   286        config xdc.runtime.Assert.Id A_noBlocksToFree =
   287            {msg: "Cannot call HeapBuf_free when no blocks have been allocated"};
   288    
   289        /*!
   290         *  ======== A_invalidFree ========
   291         *  Assert raised when an invalid free occurs
   292         *
   293         *  This assert can be caused for the following reasons
   294         *  @p(blist)
   295         *  - Passing a NULL pointer to the free.
   296         *  - The block is not within the heap's buffer range. This can occur if
   297         *    the block is freed to the wrong heap.
   298         *  - The block is not on the proper boundary. This can occur if the
   299         *    pointer returned from alloc is changed by the application and not set
   300         *    back to its original value when free is called.
   301         *  @p
   302         */
   303        config xdc.runtime.Assert.Id A_invalidFree =
   304            {msg: "A_invalidFree: Invalid free"};
   305    
   306        /*!
   307         *  ======== E_size ========
   308         *  Raised when requested size exceeds blockSize
   309         */
   310        config xdc.runtime.Error.Id E_size =
   311            {msg: "requested size is too big: handle=0x%x, size=%u"};
   312    
   313        /*!
   314         *  ======== trackMaxAllocs ========
   315         *  Track maximum number of allocations
   316         *
   317         *  This will enable/disable the tracking of the maximum number of
   318         *  allocations for a HeapBuf instance.  This maximum refers to the "all
   319         *  time" maximum number of allocations for the history of a HeapBuf
   320         *  instance, not the current number of allocations.
   321         */
   322        config Bool trackMaxAllocs = false;
   323    
   324    instance:
   325    
   326        /*!
   327         *  ======== align ========
   328         *  Alignment (in MAUs) of each block
   329         *
   330         *  The alignment must be a power of 2 that is greater than or equal to
   331         *  the target dependent value defined by
   332         *  {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}. If the default value
   333         *  of 0 is specified, this value will be changed to be the minimum
   334         *  structure alignment requirement, as defined by
   335         *  {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
   336         *
   337         *  For static creates, the HeapBuf module will allocate space for the
   338         *  buffer and will align it on this requested alignment.
   339         *
   340         *  For dynamic creates, this parameter is used solely for error checking.
   341         *  The buffer provided to a dynamically created HeapBuf must be aligned
   342         *  manually, and an assert will be raised if the buffer is not properly
   343         *  aligned. For dynamic creates, HeapBuf will NOT adjust the buffer to
   344         *  satisfy the alignment.
   345         *
   346         */
   347        config SizeT align = 0;
   348    
   349        /*!
   350         *  ======== sectionName ========
   351         *  Section name for the buffer managed by the instance
   352         *
   353         *  The buffer allocated for a statically created HeapBuf instance will be
   354         *  placed in this section.
   355         *
   356         *  The default section is the 'dataSection' in the platform.
   357         */
   358        metaonly config String sectionName = null;
   359    
   360        /*!
   361         *  ======== numBlocks ========
   362         *  Number of fixed-size blocks
   363         *
   364         *  Required parameter.
   365         *
   366         *  The default number of blocks is 0.
   367         */
   368        config UInt numBlocks = 0;
   369    
   370        /*!
   371         *  ======== blockSize ========
   372         *  Size (in MAUs) of each block
   373         *
   374         *  HeapBuf will round the blockSize up to the nearest multiple of the
   375         *  alignment, so the actual blockSize may be larger. When creating a
   376         *  HeapBuf dynamically, this needs to be taken into account to determine
   377         *  the proper buffer size to pass in.
   378         *
   379         *  Required parameter.
   380         *
   381         *  The default size of the blocks is 0 MAUs.
   382         */
   383        config SizeT blockSize = 0;
   384    
   385        /*!
   386         *  ======== bufSize ========
   387         *  Size (in MAUs) of the entire buffer; for dynamic creates only
   388         *
   389         *  When dynamically creating a HeapBuf, this should be the actual size
   390         *  of the memory buffer provided for HeapBuf to manage.
   391         *
   392         *  This parameter is used solely for error checking; an Error is raised
   393         *  if the bufSize is too small for the requested blockSize and numBlocks.
   394         *  Because of minimum alignment considerations, it's easy to provide too
   395         *  small of a buffer to manage, and difficult to detect if it happened.
   396         *
   397         *  This parameter is required for dynamic creates and ignored for static
   398         *  creates.
   399         *
   400         *  The default buffer size is 0 MAUs.
   401         */
   402        config xdc.runtime.Memory.Size bufSize = 0;
   403    
   404        /*!
   405         *  ======== buf ========
   406         *  User supplied buffer; for dynamic creates only
   407         *
   408         *  The caller must supply the memory buffer for a dynamically created
   409         *  HeapBuf to manage. The provided buffer must be aligned according to the
   410         *  HeapBuf's alignment parameter. i.e., if a buffer's alignment parameter
   411         *  is 128, then the buffer's start address must be a multiple of 128.
   412         *
   413         *  For static creates, the buffer is allocated automatically based on the
   414         *  blockSize and numBlocks parameters.
   415         *
   416         *  This parameter is required for dynamic creates and ignored for static
   417         *  creates.
   418         *
   419         */
   420        config Ptr buf = 0;
   421    
   422        /*!
   423         *  ======== alloc ========
   424         *  @HeapBuf All alignment is handled in the create, therefore the
   425         *  align argument in alloc is ignored.
   426         *
   427         *  HeapBuf_alloc will only fail if there are no available blocks or if the
   428         *  requested block size is larger than the HeapBuf's blockSize. All other
   429         *  requests, regardless of size, will succeed.
   430         */
   431        override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
   432    
   433        /*!
   434         *  ======== isBlocking ========
   435         *  @HeapBuf This function always returns FALSE since the alloc/free
   436         *  never block on a resource.
   437         */
   438        override Bool isBlocking();
   439    
   440        /*!
   441         *  ======== getBlockSize ========
   442         *  @_nodoc
   443         *  Returns the HeapBuf's actual blockSize (adjusted for alignment)
   444         *
   445         *  This getter is provided to allow other memory managers to build off
   446         *  of HeapBuf.
   447         *
   448         *  The blockSize returned has been adjusted to match the alignment,
   449         *  so it may be larger than the user-specified blockSize.
   450         */
   451        SizeT getBlockSize();
   452    
   453        /*!
   454         *  ======== getAlign ========
   455         *  @_nodoc
   456         *  Returns the HeapBuf's actual alignment (adjusted for minimum
   457         *  alignment requirements)
   458         *
   459         *  This getter is provided to allow other memory managers to build off
   460         *  of HeapBuf.
   461         */
   462        SizeT getAlign();
   463    
   464        /*!
   465         *  ======== getEndAddr ========
   466         *  @_nodoc
   467         *  Returns the last address in the buffer managed by the HeapBuf
   468         *
   469         *  This getter is provided to allow other memory managers to build off
   470         *  of HeapBuf:  Compare a block's address to the end address of the buffer
   471         *  to determine which buffer the block came from. The end address is the
   472         *  last address in the buffer, not the next address after the buffer.
   473         *
   474         *  This will not return the correct value after addMemory has been called
   475         *  to add a noncontiguous buffer of memory to the HeapBuf.
   476         *
   477         */
   478        Ptr getEndAddr();
   479    
   480        /*! ======== getExtendedStats ========
   481         *  Retrieves the extended statistics for a HeapBuf instance.
   482         *
   483         *  This function retrieves the extended statistics for a HeapBuf instance.
   484         *  It does not retrieve the standard xdc.runtime.Memory.Stats information.
   485         *
   486         *  @param(stats)  Location for the returned extended statistics.
   487         */
   488        Void getExtendedStats(ExtendedStats *stats);
   489    
   490        /*!
   491         *  ======== mergeHeapBufs ========
   492         *  @_nodoc
   493         */
   494        Void mergeHeapBufs(HeapBuf.Handle heapBuf2);
   495    
   496    internal:   /* not for client use */
   497    
   498        /*!
   499         *  ======== numConstructedHeaps ========
   500         *  @_nodoc
   501         *  Number of statically constructed Heap objects.
   502         *  Shouldn't be set directly by the user's
   503         *  config (it gets set by instance$static$init).
   504         */
   505        config UInt numConstructedHeaps = 0;
   506    
   507        /*
   508         *  ======== postInit ========
   509         *  finish initializing static and dynamic HeapBufs
   510         */
   511        Void postInit(Object *heap);
   512    
   513        /*
   514         *  ======== Instance_State ========
   515         *  Instance state
   516         */
   517        struct Instance_State {
   518            SizeT        blockSize;             /* True size of each block       */
   519            SizeT        align;                 /* Alignment of each block       */
   520            UInt         numBlocks;             /* Number of individual blocks.  */
   521            xdc.runtime.Memory.Size bufSize;    /* Size of the entire buffer     */
   522            Char         buf[];                 /* Memory managed by instance    */
   523            ti.sysbios.knl.Queue.Object freeList;  /* List of free buffers      */
   524            UInt         numFreeBlocks;
   525            UInt         minFreeBlocks;         /* used to compute max # allocs  */
   526        };
   527    
   528        /*
   529         *  ======== Module_State ========
   530         *  Module state
   531         */
   532        struct Module_State {
   533            Handle  constructedHeaps[];         /* array of statically */
   534                                                /* constructed Heaps */
   535        };
   536    }