1    /* 
     2     * Copyright (c) 2009
     3     * Texas Instruments
     4     *
     5     *  All rights reserved.  Property of Texas Instruments
     6     *  Restricted rights to use, duplicate or disclose this code are
     7     *  granted through contract.
     8     * 
     9     * */
    10    /*
    11     *  ======== HeapBuf.xdc ========
    12     *
    13     */
    14    
    15    package ti.sysbios.heaps;
    16    
    17    import xdc.rov.ViewInfo;
    18    
    19    /*!
    20     *  ======== HeapBuf ========
    21     *  Fixed size buffer heap implementation.
    22     *
    23     *  The HeapBuf manager provides functions to allocate and free storage from a
    24     *  heap of type HeapBuf which inherits from IHeap. HeapBuf manages a single
    25     *  fixed-size buffer, split into equally sized allocable blocks.
    26     *
    27     *  The HeapBuf manager is intended as a very fast and deterministic memory
    28     *  manager which can only allocate blocks of a single size. It is ideal for
    29     *  managing a heap that is only used for allocating a single type of object,
    30     *  or for objects that have very similar sizes.
    31     *
    32     *  Allocation from and freeing to a HeapBuf instance is non-blocking and 
    33     *  deterministic: a call to alloc or free will always take the same amount of
    34     *  time.
    35     *
    36     *  Constraints:
    37     *  @p(blist)
    38     *  - Align parameter must be set to 0 for default, or be a power of 2 that is
    39     *    greater than or equal to the value returned by
    40     *    {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
    41     *  - The buffer passed to dynamically create a HeapBuf must be aligned
    42     *    according to the alignment parameter, and must be large enough to account
    43     *    for the actual block size after it has been rounded up to a multiple of 
    44     *    the alignment. 
    45     *  @p
    46     *
    47     *  @p(html)
    48     *  <h3> Calling Context </h3>
    49     *  <table border="1" cellpadding="3">
    50     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
    51     *
    52     *    <tr><th> Function    </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    53     *    <!--                                                                                                                        -->
    54     *    <tr><td> Params_init      </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
    55     *    <tr><td> alloc            </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    56     *    <tr><td> construct        </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    57     *    <tr><td> create           </td><td>   N*   </td><td>   N*   </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    58     *    <tr><td> delete           </td><td>   N*   </td><td>   N*   </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    59     *    <tr><td> destruct         </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    60     *    <tr><td> free             </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    61     *    <tr><td> getStats         </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    62     *    <tr><td> getExtendedStats </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    63     *    <tr><td> isBlocking       </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    64     *    <tr><td colspan="6"> Definitions: <br />
    65     *       <ul>
    66     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
    67     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
    68     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
    69     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
    70     *           <ul>
    71     *             <li> In your module startup after this module is started (e.g. HeapBuf_Module_startupDone() returns TRUE). </li>
    72     *             <li> During xdc.runtime.Startup.lastFxns. </li>
    73     *             <li> During main().</li>
    74     *             <li> During BIOS.startupFxns.</li>
    75     *           </ul>
    76     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
    77     *           <ul>
    78     *             <li> During xdc.runtime.Startup.firstFxns.</li>
    79     *             <li> In your module startup before this module is started (e.g. HeapBuf_Module_startupDone() returns FALSE).</li>
    80     *           </ul>
    81     *       </ul>
    82     *       <li> <b>*</b>:  Assuming blocking Heap is used for creation. </li>
    83     *       <li> <b>**</b>: Assuming GateMutex is used as HeapMem's Gate. </li>
    84     *       <li> <b>+</b> : Cannot use HeapMem object while it is being restored. </li>
    85     *    </td></tr>
    86     *  
    87     *  </table>
    88     *  @p
    89     */
    90    
    91    @InstanceInitError /* Initialization may throw errors */
    92    @ModuleStartup     /* Instances require more initialization at startup */
    93    @InstanceFinalize  /* Destroys the freeList Q */
    94    
    95    module HeapBuf inherits xdc.runtime.IHeap {
    96        
    97        metaonly struct BasicView {
    98            String    label;
    99            xdc.runtime.Memory.Size bufSize;    /* Size of the entire buffer     */
   100            SizeT     align;
   101            SizeT     blockSize;
   102            UInt      numBlocks;
   103            Int       totalFreeSize;
   104            UInt      numberAllocatedBlocks;
   105            UInt      numFreeBlocks;
   106            UInt      maxAllocatedBlocks;
   107            Ptr       buf;
   108    
   109            // statStr contains "quick" info 4 HeapBuf that other mods will display.
   110            // statStr won't be displayed by the HeapBuf ROV view itself.
   111            String    statStr; 
   112        }
   113        
   114        metaonly struct DetailedView {
   115            String    label;
   116            xdc.runtime.Memory.Size bufSize;    /* Size of the entire buffer     */
   117            SizeT     align;
   118            SizeT     blockSize;
   119            UInt      numBlocks;
   120            Int       totalFreeSize;
   121            UInt      numberAllocatedBlocks;
   122            UInt      numFreeBlocks;
   123            UInt      maxAllocatedBlocks;
   124            Ptr       buf;
   125            Ptr       freeList;
   126    
   127            // statStr contains "quick" info 4 HeapBuf that other mods will display.
   128            // statStr won't be displayed by the HeapBuf ROV view itself.
   129            String    statStr; 
   130        }
   131    
   132        /*! @_nodoc */
   133        @Facet
   134        metaonly config ViewInfo.Instance rovViewInfo = 
   135            ViewInfo.create({
   136                viewMap: [
   137                        ['Basic',    {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitInstance', structName: 'BasicView'}],
   138                        ['Detailed', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitDetailed', structName: 'DetailedView'}]
   139                ]
   140            });
   141    
   142        /*!
   143         *  ======== ExtendedStats ========
   144         *  Stats structure for the getExtendedStats API.  
   145         *
   146         *  @field(maxAllocatedBlocks) The maximum number of blocks allocated from
   147         *                             this heap at any single point in time, during
   148         *                             the lifetime of this HeapBuf instance.
   149         *
   150         *  @field(numAllocatedBlocks) The total number of blocks currently
   151         *                             allocated in this HeapBuf instance.
   152         */
   153        struct ExtendedStats {
   154            UInt maxAllocatedBlocks;
   155            UInt numAllocatedBlocks;
   156        }
   157    
   158        /*!
   159         *  Assert raised when the buf parameter has been omitted (null) for a 
   160         *  dynamic create.
   161         */
   162        config xdc.runtime.Assert.Id A_nullBuf = 
   163            {msg: "buf parameter cannot be null"};
   164        
   165        /*!
   166         *  Assert raised when the buf parameter has not been aligned on the 
   167         *  requested alignment.
   168         */
   169        config xdc.runtime.Assert.Id A_bufAlign = 
   170            {msg: "buf not properly aligned"};
   171        
   172        /*!
   173         *  Assert raised when the align parameter is not the default value of zero,
   174         *  or a power of 2 that is greater than or equal to the value defined by
   175         *  {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
   176         */
   177        config xdc.runtime.Assert.Id A_invalidAlign = 
   178            {msg: "align parameter must be 0 or a power of 2 >= the value of Memory_getMaxDefaultTypeAlign()"};
   179    
   180        /*!
   181         *  Assert raised when the blockSize parameter is 0.
   182         */
   183        config xdc.runtime.Assert.Id A_zeroBlockSize = 
   184            {msg: "blockSize cannot be zero"};
   185        
   186        /*!
   187         *  Assert raised when the numBlocks parameter is 0.
   188         */
   189        config xdc.runtime.Assert.Id A_zeroBlocks = 
   190            {msg: "numBlocks cannot be zero"};
   191            
   192        /*!
   193         *  Assert raised when the bufSize parameter is 0.
   194         */
   195        config xdc.runtime.Assert.Id A_zeroBufSize = 
   196            {msg: "bufSize cannot be zero"};
   197            
   198        /*!
   199         *  Assert raised when the bufSize parameter is too small
   200         *  to handle requested blocks.
   201         */
   202        config xdc.runtime.Assert.Id A_invalidBufSize = 
   203            {msg: "HeapBuf_create's bufSize parameter is invalid (too small)"};
   204    
   205        /*!
   206         *  Assert raised when free is called and there are no blocks allocated.
   207         */
   208        config xdc.runtime.Assert.Id A_noBlocksToFree = 
   209            {msg: "Cannot call HeapBuf_free when no blocks have been allocated"};
   210    
   211        /*!
   212         *  This will enable/disable the tracking of the maximum number of
   213         *  allocations for a HeapBuf instance.  This maximum refers to the "all
   214         *  time" maximum number of allocations for the history of a HeapBuf
   215         *  instance, not the current number of allocations.
   216         */
   217        config Bool trackMaxAllocs = false;
   218    
   219    instance:
   220    
   221        /*! 
   222         *  Alignment (in MAUs) of each block.
   223         *
   224         *  The alignment must be a power of 2 that is greater than or equal to
   225         *  the target dependent value defined by
   226         *  {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}. If the default value
   227         *  of 0 is specified, this value will be changed to be the minimum
   228         *  structure alignment requirement, as defined by 
   229         *  {@link xdc.runtime.Memory#getMaxDefaultTypeAlign}.
   230         *
   231         *  For static creates, the HeapBuf module will allocate space for the
   232         *  buffer and will align it on this requested alignment. 
   233         *  
   234         *  For dynamic creates, this parameter is used solely for error checking.
   235         *  The buffer provided to a dynamically created HeapBuf must be aligned
   236         *  manually, and an assert will be raised if the buffer is not properly
   237         *  aligned. For dynamic creates, HeapBuf will NOT adjust the buffer to
   238         *  satisfy the alignment.
   239         *
   240         */
   241        config SizeT align = 0;    
   242        
   243        /*!
   244         *  ======== sectionName ========
   245         *  Section name for the buffer managed by the instance.
   246         *
   247         *  The buffer allocated for a statically created HeapBuf instance will be
   248         *  placed in this section.
   249         *
   250         *  The default section is the 'dataSection' in the platform.
   251         */
   252       metaonly config String sectionName = null;
   253    
   254        /*! 
   255         *  Number of fixed-size blocks.
   256         *
   257         *  Required parameter.
   258         *
   259         *  The default number of blocks is 0.
   260         */
   261        config UInt numBlocks = 0;
   262        
   263        /*!
   264         *  Size (in MAUs) of each block.
   265         *
   266         *  HeapBuf will round the blockSize up to the nearest multiple of the
   267         *  alignment, so the actual blockSize may be larger. When creating a
   268         *  HeapBuf dynamically, this needs to be taken into account to determine
   269         *  the proper buffer size to pass in.
   270         *
   271         *  Required parameter.
   272         *
   273         *  The default size of the blocks is 0 MAUs.
   274         */
   275        config SizeT blockSize = 0;
   276        
   277        /*!
   278         *  Size (in MAUs) of the entire buffer; for dynamic creates only.
   279         *
   280         *  When dynamically creating a HeapBuf, this should be the actual size
   281         *  of the memory buffer provided for HeapBuf to manage.
   282         *
   283         *  This parameter is used soley for error checking; an Error is raised
   284         *  if the bufSize is too small for the requested blockSize and numBlocks.
   285         *  Because of minimum alignment considerations, it's easy to provide too
   286         *  small of a buffer to manage, and difficult to detect if it happened.
   287         *
   288         *  This parameter is required for dynamic creates and ignored for static
   289         *  creates.
   290         *
   291         *  The default buffer size is 0 MAUs.
   292         */
   293        config xdc.runtime.Memory.Size bufSize = 0;
   294        
   295        /*! 
   296         *  User supplied buffer; for dynamic creates only.
   297         *
   298         *  The caller must supply the memory buffer for a dynamically created 
   299         *  HeapBuf to manage. The provided buffer must be aligned according to the
   300         *  HeapBuf's alignment parameter. i.e., if a buffer's alignment parameter
   301         *  is 128, then the buffer's start address must be a multiple of 128. 
   302         *
   303         *  For static creates, the buffer is allocated automatically based on the
   304         *  blockSize and numBlocks parameters.
   305         *
   306         *  This parameter is required for dynamic creates and ignored for static
   307         *  creates.
   308         *
   309         */
   310        config Ptr buf = 0;
   311       
   312        /*!
   313         *  @HeapBuf All alignment is handled in the create, therefore the 
   314         *  align argument in alloc is ignored.
   315         *  
   316         *  HeapBuf_alloc will only fail if there are no available blocks or if the
   317         *  requested block size is larger than the HeapBuf's blockSize. All other
   318         *  requests, regardless of size, will succeed.     
   319         */
   320        override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
   321        
   322        /*!
   323         *  @HeapBuf This function always returns FALSE since the alloc/free
   324         *  never block on a resource.
   325         */
   326        override Bool isBlocking();    
   327        
   328        /*!
   329         *  ======== getBlockSize ========
   330         *  @_nodoc
   331         *  Returns the HeapBuf's actual blockSize (adjusted for alignment).
   332         *
   333         *  This getter is provided to allow other memory managers to build off
   334         *  of HeapBuf.
   335         *
   336         *  The blockSize returned has been adjusted to match the alignment,
   337         *  so it may be larger than the user-specified blockSize.
   338         */
   339        SizeT getBlockSize();
   340        
   341        /*!
   342         *  ======== getAlign ========
   343         *  @_nodoc
   344         *  Returns the HeapBuf's actual alignment (adjusted for minimum 
   345         *  alignment requirements).
   346         *
   347         *  This getter is provided to allow other memory managers to build off
   348         *  of HeapBuf.
   349         */
   350        SizeT getAlign();
   351        
   352        /*!
   353         *  ======== getEndAddr ========
   354         *  @_nodoc
   355         *  Returns the last address in the buffer managed by the HeapBuf.
   356         *
   357         *  This getter is provided to allow other memory managers to build off
   358         *  of HeapBuf:  Compare a block's address to the end address of the buffer
   359         *  to determine which buffer the block came from. The end address is the 
   360         *  last address in the buffer, not the next address after the buffer.
   361         *
   362         *  This will not return the correct value after addMemory has been called
   363         *  to add a noncontiguous buffer of memory to the HeapBuf.
   364         *
   365         */
   366        Ptr getEndAddr();
   367    
   368        /*! ======== getExtendedStats ========
   369         *  @a(HeapBuf)
   370         *  Retrieves the extended statistics for a HeapBuf instance.
   371         *
   372         *  This function retrieves the extended statistics for a HeapBuf instance.
   373         *  It does not retrieve the standard xdc.runtime.Memory.Stats information.
   374         *
   375         *  @param(stats)  Location for the returned extended statistics.
   376         */
   377        Void getExtendedStats(ExtendedStats *stats);
   378        
   379        /*!
   380         *  ======== mergeHeapBufs ========
   381         *  @_nodoc
   382         */
   383        Void mergeHeapBufs(HeapBuf.Handle heapBuf2);
   384        
   385    internal:   /* not for client use */
   386        /*!
   387         *  @_nodoc
   388         *  Number of statically constructed Heap objects.
   389         *  Shouldn't be set directly by the user's
   390         *  config (it gets set by instance$static$init).
   391         */
   392        config UInt numConstructedHeaps = 0;
   393    
   394        
   395        
   396        /* instance object */
   397        struct Instance_State {        
   398            SizeT        blockSize;             /* True size of each block       */
   399            SizeT        align;                 /* Alignment of each block       */
   400            UInt         numBlocks;             /* Number of individual blocks.  */
   401            xdc.runtime.Memory.Size bufSize;    /* Size of the entire buffer     */
   402            Char         buf[];                 /* Memory managed by instance    */
   403            ti.sysbios.misc.Queue.Object freeList;  /* List of free buffers      */
   404            UInt         numFreeBlocks;
   405            UInt         minFreeBlocks;         /* used to compute max # allocs  */
   406        };
   407    
   408        struct Module_State {
   409            Handle  constructedHeaps[];         /* array of statically */
   410                                                /* constructed Heaps */
   411        };
   412    }
   413    /*
   414     *  @(#) ti.sysbios.heaps; 2, 0, 0, 0,349; 12-18-2009 15:12:56; /db/vtree/library/trees/avala/avala-m19x/src/
   415     */
   416