1    /*
     2     * Copyright (c) 2015-2017, 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     *  In addition to allowing multiple static HeapMem instances to be created
    51     *  who's buffer placements and sizes are defined by their instance
    52     *  configuration parameters,
    53     *  HeapMem allows one Heap instance to be defined who's heap
    54     *  memory is defined by buffer start and end symbols in the linker command
    55     *  file. This singular Heap instance is referred to as the 'Primary Heap'.
    56     *
    57     *  see {@link #primaryHeapBaseAddr}, {@link #primaryHeapEndAddr},
    58     *  and {@link #usePrimaryHeap}
    59     *
    60     *  @p(html)
    61     *  <h3> HeapMem Gate </h3>
    62     *  A HeapMem instance will use the HeapMem module Gate to protect any accesses
    63     *  to its list of free memory blocks. The HeapMem instance will enter and
    64     *  leave the module Gate when allocating blocks, freeing blocks, and
    65     *  retrieving statistics about the HeapMem.
    66     *
    67     *  By default, the Gate is of type GateMutex.
    68     *
    69     *  A different Gate can be specified using the common$.gate parameter.
    70     *  For example, to use a GateTask to protect HeapMem:
    71     *      HeapMem.common$.gate = GateTask.create();
    72     *
    73     *  To save on overhead, HeapMem does not create additional Gate instances on a
    74     *  per-instance basis; there is only one Gate instance shared across all of
    75     *  the HeapMem instances. Therefore, the HeapMem.common$.gateParams parameter
    76     *  (used for configuring per-instance Gates) is ignored.
    77     *
    78     *  The type of Gate used should be chosen based on the type of threads (Hwi,
    79     *  Swi, Task, etc.) using the heap. It should also consider the
    80     *  non-deterministic nature of the HeapMem. A call to alloc or free will
    81     *  traverse a list of free blocks, so a GateHwi, for example, is likely an
    82     *  inappropriate Gate for HeapMem.
    83     *
    84     *  @p(html)
    85     *  <h3> Calling Context </h3>
    86     *  <table border="1" cellpadding="3">
    87     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center">
    88     *    </colgroup>
    89     *
    90     *    <tr><th> Function    </th><th>  Hwi   </th><th>  Swi   </th>
    91     *    <th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    92     *    <!--                                     -->
    93     *    <tr><td> Params_init         </td><td>   Y    </td><td>   Y    </td>
    94     *    <td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
    95     *    <tr><td> alloc               </td><td>   N**  </td><td>   N**  </td>
    96     *    <td>   Y**  </td><td>   Y    </td><td>   N    </td></tr>
    97     *    <tr><td> construct           </td><td>   Y    </td><td>   Y    </td>
    98     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
    99     *    <tr><td> create              </td><td>   N*   </td><td>   N*   </td>
   100     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   101     *    <tr><td> delete              </td><td>   N*   </td><td>   N*   </td>
   102     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   103     *    <tr><td> destruct            </td><td>   Y    </td><td>   Y    </td>
   104     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   105     *    <tr><td> free                </td><td>   N**  </td><td>   N**  </td>
   106     *    <td>   Y**  </td><td>   Y    </td><td>   N    </td></tr>
   107     *    <tr><td> getExtendedStats    </td><td>   Y    </td><td>   Y    </td>
   108     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   109     *    <tr><td> getStats            </td><td>   N**  </td><td>   N**  </td>
   110     *    <td>   Y**  </td><td>   Y    </td><td>   N    </td></tr>
   111     *    <tr><td> isBlocking          </td><td>   Y    </td><td>   Y    </td>
   112     *    <td>   Y    </td><td>   Y    </td><td>   N    </td></tr>
   113     *    <tr><td> restore             </td><td>   Y+   </td><td>   Y+   </td>
   114     *    <td>   Y+   </td><td>   Y    </td><td>   N    </td></tr>
   115     *    <tr><td colspan="6"> Definitions: <br />
   116     *       <ul>
   117     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
   118     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
   119     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
   120     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
   121     *           <ul>
   122     *             <li> In your module startup after this module is started
   123     *    (e.g. HeapMem_Module_startupDone() returns TRUE). </li>
   124     *             <li> During xdc.runtime.Startup.lastFxns. </li>
   125     *             <li> During main().</li>
   126     *             <li> During BIOS.startupFxns.</li>
   127     *           </ul>
   128     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
   129     *           <ul>
   130     *             <li> During xdc.runtime.Startup.firstFxns.</li>
   131     *             <li> In your module startup before this module is started
   132     *    (e.g. HeapMem_Module_startupDone() returns FALSE).</li>
   133     *           </ul>
   134     *       <li> <b>*</b> : Assuming blocking Heap is used for creation. </li>
   135     *       <li> <b>**</b>: Assuming GateMutex is used as HeapMem's Gate. </li>
   136     *       <li> <b>+</b> : Cannot use HeapMem object while it is being
   137     *    restored. </li>
   138     *       </ul>
   139     *    </td></tr>
   140     *
   141     *  </table>
   142     *  @p
   143     */
   144    @Gated
   145    module HeapMem inherits xdc.runtime.IHeap {
   146    
   147        /*! @_nodoc */
   148        @XmlDtd
   149        metaonly struct BasicView {
   150            String            label;
   151            Ptr               buf;
   152            SizeT             minBlockAlign;
   153            String            sectionName;
   154        }
   155    
   156        /*! @_nodoc */
   157        @XmlDtd
   158        metaonly struct DetailedView {
   159            String            label;
   160            Ptr               buf;
   161            SizeT             minBlockAlign;
   162            String            sectionName;
   163            Memory.Size       totalSize;
   164            Memory.Size       totalFreeSize;
   165            Memory.Size       largestFreeSize;
   166        }
   167    
   168        /*!
   169         *  ======== FreeBlockView ========
   170         *  @_nodoc
   171         */
   172        metaonly struct FreeBlockView {
   173            String         Address;
   174            String         size;
   175            String  next;
   176            String         status;
   177        }
   178    
   179        /*! @_nodoc */
   180        @Facet
   181        metaonly config ViewInfo.Instance rovViewInfo =
   182            ViewInfo.create({
   183                viewMap: [
   184                [
   185                    'Basic',
   186                    {
   187                        type: ViewInfo.INSTANCE,
   188                        viewInitFxn: 'viewInitBasic',
   189                        structName: 'BasicView'
   190                    }
   191                ],
   192                [
   193                    'Detailed',
   194                    {
   195                        type: ViewInfo.INSTANCE,
   196                        viewInitFxn: 'viewInitDetailed',
   197                        structName: 'DetailedView'
   198                    }
   199                ],
   200                [
   201                    'FreeList',
   202                    {
   203                        type: ViewInfo.INSTANCE_DATA,
   204                        viewInitFxn: 'viewInitData',
   205                        structName: 'FreeBlockView'
   206                    }
   207                ]
   208                ]
   209            });
   210    
   211    
   212        /*!
   213         *  ======== ExtendedStats ========
   214         *  Stat structure for the HeapMem_getExtendedStats function
   215         *
   216         *  @field(buf)           Base address of the internal buffer.
   217         *                        This may be different from the original buf
   218         *                        parameter due to alignment requirements.
   219         *  @field(size)          Size of the internal buffer.
   220         *                        This may be different from the original size
   221         *                        parameter due to alignment requirements.
   222         */
   223        struct ExtendedStats {
   224            Ptr   buf;
   225            SizeT size;
   226        }
   227    
   228        /*!
   229         *  ======== A_zeroBlock ========
   230         *  Assert raised when a block of size 0 is requested
   231         *
   232         *  This error can also be raised if the requested size wraps
   233         *  the contents of a SizeT type when it is adjusted for a minimum
   234         *  alignment. For example, when SizeT is 16-bits and a size request
   235         *  is made for 0xFFFB.
   236         */
   237        config xdc.runtime.Assert.Id A_zeroBlock =
   238            {msg: "A_zeroBlock: Cannot allocate size 0"};
   239    
   240        /*!
   241         *  ======== A_heapSize ========
   242         *  Assert raised when the requested heap size is too small
   243         */
   244        config xdc.runtime.Assert.Id A_heapSize =
   245            {msg: "A_heapSize: Requested heap size is too small"};
   246    
   247        /*!
   248         *  ======== A_align ========
   249         *  Assert raised when the requested alignment is not a power of 2
   250         */
   251        config xdc.runtime.Assert.Id A_align =
   252            {msg: "A_align: Requested align is not a power of 2"};
   253    
   254        /*!
   255         *  ======== E_memory ========
   256         *  Raised when requested size exceeds largest free block
   257         */
   258        config Error.Id E_memory = {msg: "out of memory: handle=0x%x, size=%u"};
   259    
   260        /*!
   261         *  ======== A_invalidFree ========
   262         *  Assert raised when the free detects that an invalid addr or size
   263         *
   264         *  This could arise when multiple frees are done on the same buffer or
   265         *  if corruption occurred.
   266         *
   267         *  This also could occur when an alloc is made with size N and the
   268         *  free for this buffer specifies size M where M > N. Note: not every
   269         *  case is detectable.
   270         *
   271         *  This assert can also be caused when passing an invalid addr to free
   272         *  or if the size is causing the end of the buffer to be
   273         *  out of the expected range.
   274         */
   275        config xdc.runtime.Assert.Id A_invalidFree =
   276            {msg: "A_invalidFree: Invalid free"};
   277    
   278        /*!
   279         *  ======== primaryHeapBaseAddr ========
   280         *  Base address of the 'Primary Heap' buffer.
   281         *
   282         *  HeapMem allows one Heap instance to be defined who's heap
   283         *  memory is defined by symbols in the linker command file.
   284         *  This singular Heap instance is referred to as the 'Primary Heap'.
   285         *
   286         *  see {@link #primaryHeapEndAddr}
   287         *  see {@link #usePrimaryHeap}
   288         *
   289         *  The following example will create a HeapMem instance whose
   290         *  size and buffer will be determined at runtime based on the
   291         *  values of the symbols `__primary_heap_start__` and
   292         *  `__primary_heap_end__`. It is assumed the user will define these
   293         *  symbols in their linker command file.
   294         *
   295         *  @p(code)
   296         *  var HeapMem = xdc.useModule('ti.sysbios.heaps.HeapMem');
   297         *
   298         *  HeapMem.primaryHeapBaseAddr = "&__primary_heap_start__";
   299         *  HeapMem.primaryHeapEndAddr = "&__primary_heap_end__";
   300         *
   301         *  var heapMemParams = new HeapMem.Params;
   302         *  heapMemParams.usePrimaryHeap = true;
   303         *
   304         *  var heap0 = HeapMem.create(heapMemParams);
   305         *  @p
   306         */
   307        config Char *primaryHeapBaseAddr = null;
   308    
   309        /*!
   310         *  ======== primaryHeapEndAddr ========
   311         *  End address of the 'Primary Heap' buffer, plus one.
   312         *
   313         *  see {@link #primaryHeapBaseAddr}
   314         *  see {@link #usePrimaryHeap}
   315         *
   316         *  @p(code)
   317         *  HeapMem.primaryHeapEndAddr = "&__primary_heap_end__";
   318         *  @p
   319         */
   320        config Char *primaryHeapEndAddr = null;
   321    
   322        /*!
   323         *  ======== enter ========
   324         *  @_nodoc
   325         *  Enter the module's gate. This is needed to support
   326         *  the legacy MEM module. It allows MEM to use the same
   327         *  gate for thread-safety.
   328         */
   329        IArg enter();
   330    
   331        /*!
   332         *  ======== leave ========
   333         *  @_nodoc
   334         *  Leave the module's gate. This is needed to support
   335         *  the legacy MEM module. It allows MEM to use the same
   336         *  gate for thread-safety.
   337         */
   338        Void leave(IArg key);
   339    
   340    instance:
   341    
   342        /*!
   343         *  ======== usePrimaryHeap ========
   344         *  Use {@link #primaryHeapBaseAddr} and {@link #primaryHeapEndAddr}
   345         *  to define the Heap buffer managed by this static instance.
   346         *
   347         *  @a(warning)
   348         *  This instance parameter only exists for statically defined
   349         *  HeapMem objects and can only be set to true in the creation
   350         *  of one static HeapMem object!
   351         */
   352        metaonly config Bool usePrimaryHeap = false;
   353    
   354        /*!
   355         *  ======== align ========
   356         *  Alignment of the buffer being managed by this heap instance
   357         *
   358         *  In the static HeapMem.create() call, the buffer allocated for the
   359         *  HeapMem instance will have the alignment specified by this parameter.
   360         *
   361         *  In the dynamic case, the client must supply the buffer, so it is the
   362         *  client's responsibility to manage the buffer's alignment, and there is
   363         *  no 'align' parameter.
   364         *
   365         *  The specified alignment must be a power of 2.
   366         *
   367         *  HeapMem requires that the buffer be aligned on a target-specific minimum
   368         *  alignment, and will adjust (round up) the requested alignment as
   369         *  necessary to satisfy this requirement.
   370         *
   371         *  The default alignment is 0.
   372         */
   373        metaonly config SizeT align = 0;
   374    
   375        /*!
   376         *  ======== minBlockAlign ========
   377         *  Minimum alignment for each block allocated
   378         *
   379         *  This parameter dictates the minimum alignment for each
   380         *  block that is allocated. If an alignment request of greater than
   381         *  minBlockAlign is made in the alloc, it will be honored. If an
   382         *  alignment request of less than minBlockAlign is made, the request will
   383         *  be ignored and minBlockAlign will be used.
   384         *
   385         *  @p(code)
   386         *  HeapMem_Params_init(&prms);
   387         *  prms.minBlockAlign = 32;
   388         *  handle = HeapMem_create(&prms, &eb);
   389         *  ...
   390         *  // buf will be aligned on a 32 MAU boundary
   391         *  buf = Memory_alloc(HeapMem_Handle_upCast(handle), SIZE, 8, &eb);
   392         *
   393         *  // buf will be aligned on a 64 MAU boundary
   394         *  buf = Memory_alloc(HeapMem_Handle_upCast(handle), SIZE, 64, &eb);
   395         *  @p
   396         *
   397         *  The default alignment is 0 (which means this parameter is ignored).
   398         */
   399        config SizeT minBlockAlign = 0;
   400    
   401        /*!
   402         *  ======== sectionName ========
   403         *  Section name for the buffer managed by the instance
   404         *
   405         *  The default section is the 'dataSection' in the platform.
   406         */
   407        metaonly config String sectionName = null;
   408    
   409        /*!
   410         *  ======== buf ========
   411         *  Buffer being managed by this heap instance
   412         *
   413         *  This parameter is ignored in the static HeapMem.create() call. It is a
   414         *  required parameter in the dynamic HeapMem_create() call.
   415         *
   416         *  HeapMem requires that the buffer be aligned on a target-specific minimum
   417         *  alignment, and will adjust the buffer's start address and size as
   418         *  necessary to satisfy this requirement.
   419         */
   420        config Ptr buf = 0;
   421    
   422        /*!
   423         *  ======== size ========
   424         *  Size of buffer being managed by this heap instance
   425         *
   426         *  The usable size may be smaller depending on alignment requirements.
   427         */
   428        config Memory.Size size = 0;
   429    
   430        /*!
   431         *  ======== alloc ========
   432         *
   433         *  @HeapMem
   434         *  The actual block returned may be larger than requested to satisfy
   435         *  alignment requirements, and its size will always be a multiple of
   436         *  the size of the HeapMem_Header data structure (usually 8 bytes)
   437         *
   438         *  HeapMem_alloc() will lock the heap using the HeapMem Gate while it
   439         *  traverses the list of free blocks to find a large enough block for
   440         *  the request.
   441         *
   442         *  HeapMem_alloc() should not be called directly.  Application code
   443         *  should use Memory_alloc() with a HeapMem_Handle as the first
   444         *  parameter.  Among other things, Memory_alloc() makes sure that the
   445         *  alignment parameter is greater than or equal to the minimum alignment
   446         *  required for the HeapMem_Header data structure for a given C compiler
   447         *  (8 bytes in most cases). HeapMem_alloc() may crash if you pass a
   448         *  smaller alignment.
   449         *
   450         *  Guidelines for using large heaps and multiple alloc() calls.
   451         *  @p(blist)
   452         *          - If possible, allocate larger blocks first. Previous
   453         *            allocations of small memory blocks can reduce the size
   454         *            of the blocks available for larger memory allocations.
   455         *          - Realize that alloc() can fail even if the heap contains a
   456         *            sufficient absolute amount of unallocated space. This is
   457         *            because the largest free memory block may be smaller than
   458         *            total amount of unallocated memory.
   459         *  @p
   460         *
   461         *  @param(size)  Requested size
   462         *  @param(align) Requested alignment
   463         *  @param(eb)    Error_Block used to denote location in case of a failure
   464         *
   465         *  @b(returns)    allocated block or NULL is request cannot be honored
   466         */
   467        override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
   468    
   469        /*!
   470         *  ======== allocUnprotected ========
   471         *
   472         *  @HeapMem
   473         *  The actual block returned may be larger than requested to satisfy
   474         *  alignment requirements
   475         *
   476         *  HeapMem_allocUnprotected() will
   477         *  traverses the list of free blocks to find a large enough block for
   478         *  the request.
   479         *
   480         *  The caller of this API must provider the thread-safety
   481         *  of this call.
   482         *
   483         *  Guidelines for using large heaps and multiple alloc() calls.
   484         *  @p(blist)
   485         *          - If possible, allocate larger blocks first. Previous
   486         *            allocations of small memory blocks can reduce the size
   487         *            of the blocks available for larger memory allocations.
   488         *          - Realize that alloc() can fail even if the heap contains a
   489         *            sufficient absolute amount of unallocated space. This is
   490         *            because the largest free memory block may be smaller than
   491         *            total amount of unallocated memory.
   492         *  @p
   493         *
   494         *  @param(size)  Requested size
   495         *  @param(align) Requested alignment
   496         *
   497         *  @b(returns)    allocated block or NULL is request cannot be honored
   498         */
   499        Ptr allocUnprotected(SizeT size, SizeT align);
   500    
   501        /*!
   502         *  ======== free ========
   503         *
   504         *  @HeapMem
   505         *  free() places the memory block specified by addr and size back into the
   506         *  free pool of the heap specified. The newly freed block is combined with
   507         *  any adjacent free blocks. The space is then available for further
   508         *  allocation by alloc().
   509         *
   510         *  free() will lock the heap using the HeapMem Gate, if one is specified
   511         *  using 'HeapMem.common$.gate'.
   512         *
   513         *  @param(block) Block to be freed
   514         *  @param(size)  Size of block to free
   515         */
   516        override Void free(Ptr block, SizeT size);
   517    
   518        /*!
   519         *  ======== freeUnprotected ========
   520         *
   521         *  @HeapMem
   522         *  freeNoGate() places the memory block specified by addr and size back into the
   523         *  free pool of the heap specified. The newly freed block is combined with
   524         *  any adjacent free blocks. The space is then available for further
   525         *  allocation by alloc().
   526         *
   527         *  The caller of this API must provider the thread-safety
   528         *  of this call.
   529         *
   530         *  @param(block) Block to be freed
   531         *  @param(size)  Size of block to free
   532         */
   533        Void freeUnprotected(Ptr block, SizeT size);
   534    
   535        /*!
   536         *  ======== isBlocking ========
   537         *
   538         *  @HeapMem
   539         *  This function queries the gate (as specified by 'HeapMem.common$.gate')
   540         *  to determine if the alloc/free can be blocking.
   541         */
   542        override Bool isBlocking();
   543    
   544        /*!
   545         *  ======== getStats ========
   546         *
   547         *  @HeapMem
   548         *  getStats() will lock the heap using the HeapMem Gate while it retrieves
   549         *  the HeapMem's statistics.
   550         *
   551         *  The returned totalSize reflects the usable size of the buffer, not
   552         *  necessarily the size specified during create.
   553         */
   554        override Void getStats(xdc.runtime.Memory.Stats *stats);
   555    
   556    
   557        /*!
   558         *  ======== restore ========
   559         *  Restores an instance to its original created state
   560         *
   561         *  This function restores a static or dynamically created instance to
   562         *  its original created state. Any memory previously allocated from the
   563         *  heap is no longer valid after this API is called. This function
   564         *  does not check whether there is allocated memory or not.
   565         */
   566        Void restore();
   567    
   568        /*!
   569         *  ======== getExtendedStats ========
   570         *  Retrieves the extended statistics for a HeapMem instance
   571         *
   572         *  This function retrieves the extended statistics for a HeapMem instance.
   573         *  It does not retrieve the standard xdc.runtime.Memory.Stats information.
   574         *
   575         *  @param(stats)  Location for the returned extended statistics.
   576         */
   577        Void getExtendedStats(ExtendedStats *stats);
   578    
   579    
   580    internal:   /* not for client use */
   581    
   582        /*!
   583         *  ======== init ========
   584         *  Initialize instance at runtime
   585         *
   586         *  This function is plugged as a Startup.firstFxn so that the
   587         *  HeapMem objects are ready and usable by malloc() and
   588         *  Memory_alloc() by the time the module startup functions
   589         *  get called so that any calls to atexit(), which in some targets
   590         *  invokes malloc(), will be handled cleanly.
   591         */
   592        Void init();
   593    
   594        /*!
   595         *  ======== initPrimary ========
   596         *  Initialize instance at runtime
   597         *
   598         *  Same as 'init' but supports the use of 'HeapMem.primaryHeapBaseAddress'.
   599         */
   600        Void initPrimary();
   601    
   602        /* Required alignment. Must be a power of 2 */
   603        config SizeT reqAlign;
   604    
   605        /* Header maintained at the lower address of every free block */
   606        struct Header {
   607            Header *next;
   608            Memory.Size size;
   609        };
   610    
   611        struct Instance_State {
   612            xdc.runtime.Memory.Size align;
   613            Char                    buf[];      /* The heap used by HeapMem. */
   614            Header                  head;       /* First free block pointer.
   615                                                 * The size field will be used
   616                                                 * to store original heap size.
   617                                                 */
   618            SizeT                   minBlockAlign;
   619        };
   620    }
   621