1    /* --COPYRIGHT--,BSD
     2     * Copyright (c) $(CPYYEAR), 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     * --/COPYRIGHT--*/
    32    /*
    33     *  ======== HeapMultiBufMP.xdc ========
    34     *
    35     * 
    36     *! Revision History
    37     *! ================
    38     *! 12-Feb-2009 skp     SDOCM00066723 (Remove 'version' field from Attrs)
    39     *! 09-Dec-2009 skp     Common-header changes
    40     *! 10-Nov-2009 skp     Minor pre-review cleanup
    41     *! 11-Sep-2009 skp     Support for GateMP and new SharedRegion
    42     *! 20-Aug-2009 skp     Added ROV views, static support
    43     *! 03-Aug-2008 toddm   Stolen from avala-i18
    44     */
    45    
    46    package ti.sdo.ipc.heaps;
    47    
    48    import ti.sdo.ipc.SharedRegion;
    49    import ti.sdo.ipc.Ipc;
    50    import ti.sdo.ipc.GateMP;
    51    import ti.sdo.utils.NameServer;
    52    
    53    import xdc.rov.ViewInfo;    /* Display local/shared state + FreeBlockView */
    54    
    55    import xdc.runtime.Error;
    56    import xdc.runtime.Assert;
    57    import xdc.runtime.Memory;
    58    import xdc.runtime.Startup;
    59    
    60    /*!
    61     *  ======== HeapMultiBufMP ========
    62     *  Multi-processor fixed-size buffer heap implementation
    63     *
    64     *  @p(html)
    65     *  This module has a common header that can be found in the {@link ti.ipc}
    66     *  package.  Application code should include the common header file (not the 
    67     *  RTSC-generated one):
    68     *
    69     *  <PRE>#include &lt;ti/ipc/HeapMultiBufMP.h&gt;</PRE>
    70     *   
    71     *  The RTSC module must be used in the application's RTSC configuration file 
    72     *  (.cfg) if runtime APIs will be used in the application:
    73     *  
    74     *  <PRE>HeapMultiBufMP = xdc.useModule('ti.sdo.ipc.heaps.HeapMultiBufMP');
    75     *  </PRE>
    76     *
    77     *  Documentation for all runtime APIs, instance configuration parameters, 
    78     *  error codes macros and type definitions available to the application 
    79     *  integrator can be found in the 
    80     *  <A HREF="../../../../../doxygen/html/files.html">Doxygen documenation</A>
    81     *  for the IPC product.  However, the documentation presented on this page 
    82     *  should be referred to for information specific to the RTSC module, such as
    83     *  module configuration, Errors, and Asserts.
    84     *  @p
    85     *
    86     *  It is important to note that max allocation tracking is disabled by default 
    87     *  in {@link #trackMaxAllocs}.  Disabling allocation tracking improves alloc/
    88     *  free performance especially when cache calls are required in shared memory.
    89     */
    90    @InstanceInitError
    91    @InstanceFinalize
    92    
    93    module HeapMultiBufMP inherits xdc.runtime.IHeap 
    94    {
    95        /*! @_nodoc */
    96        metaonly struct BasicView {
    97            String          name;
    98            Ptr             buf;
    99            Memory.Size     totalSize;
   100            String          objType;
   101            Ptr             gate;
   102            Bool            exact;
   103        }
   104        
   105        /*! @_nodoc */
   106        metaonly struct BucketsView {
   107            Ptr             baseAddr;
   108            UInt            blockSize;
   109            UInt            align;
   110            UInt            numBlocks;
   111            UInt            numFreeBlocks;
   112            UInt            minFreeBlocks;
   113        }
   114    
   115        /*! @_nodoc */
   116        @Facet
   117        metaonly config ViewInfo.Instance rovViewInfo =
   118            ViewInfo.create({
   119                viewMap: [
   120                [   
   121                    'Basic',
   122                    {
   123                        type: ViewInfo.INSTANCE,
   124                        viewInitFxn: 'viewInitBasic',
   125                        structName: 'BasicView'
   126                    }
   127                ],
   128                [   
   129                    'Buffer Information',
   130                    {
   131                        type: ViewInfo.INSTANCE_DATA,
   132                        viewInitFxn: 'viewInitData',
   133                        structName: 'BucketsView'
   134                    }
   135                ],
   136                ]
   137            });
   138            
   139        /*! 
   140         *  Structure for bucket configuration
   141         *
   142         *  An array of buckets is a required parameter to create any 
   143         *  HeapMultiBufMP instance.  The fields of each bucket correspond
   144         *  to the attributes of each buffer in the HeapMultiBufMP.  The actual
   145         *  block sizes and alignments may be adjusted per the process described
   146         *  at {@link #bucketEntries}.
   147         *
   148         *  @field(blockSize)       Size of each block (in MADUs)
   149         *  @field(numBlocks)       Number of blocks
   150         *  @field(align)           Alignment of each block (in MADUs)
   151         */    
   152        struct Bucket {
   153            SizeT       blockSize;
   154            UInt        numBlocks;
   155            SizeT       align;
   156        }
   157    
   158        /*!
   159         *  ======== ExtendedStats ========
   160         *  Stats structure for the getExtendedStats API.  
   161         *
   162         *  @field(numBuckets)         Number of buckets
   163         *  @field(numBlocks)          Number of blocks in each buffer
   164         *  @field(blockSize)          Block size of each buffer     
   165         *  @field(align)              Alignment of each buffer
   166         *  @field(maxAllocatedBlocks) The maximum number of blocks allocated from
   167         *                             this heap at any single point in time during
   168         *                             the lifetime of this HeapMultiBufMP instance
   169         *
   170         *  @field(numAllocatedBlocks) The total number of blocks currently
   171         *                             allocated in this HeapMultiBufMP instance
   172         */
   173        struct ExtendedStats {
   174            UInt numBuckets;
   175            UInt numBlocks          [8];
   176            UInt blockSize          [8];
   177            UInt align              [8];
   178            UInt maxAllocatedBlocks [8];
   179            UInt numAllocatedBlocks [8];
   180        }
   181            
   182        /*!
   183         *  Assert raised when the align parameter is not a power of 2.
   184         */
   185        config Assert.Id A_invalidAlign = 
   186            {msg: "align parameter must be a power of 2"};
   187    
   188        /*! 
   189         *  Assert raised when an invalid buffer size was passed to free() 
   190         */
   191        config Assert.Id A_sizeNotFound = 
   192            {msg: "an invalid buffer size was passed to free"};
   193            
   194        /*! 
   195         *  Assert raised when an invalid block address was passed to free() 
   196         */
   197        config Assert.Id A_addrNotFound = 
   198            {msg: "an invalid buffer address was passed to free"};
   199            
   200        /*!
   201         *  Error raised when exact matching failed
   202         */
   203        config Error.Id E_exactFail =
   204            {msg: "E_exactFail: Exact allocation failed (requested size = %u and buffer size = %u)"};        
   205            
   206        /*!
   207         *  Error raised when requested size exceeds all blockSizes.
   208         */
   209        config Error.Id E_size = 
   210            {msg: "E_size: requested size/alignment is too big (requested size = %u and requested align = %u)"};
   211            
   212        /*!
   213         *  Error raised when there are no blocks left in the buffer corresponding to the requested size/alignment
   214         */
   215        config Error.Id E_noBlocksLeft = 
   216            {msg: "E_noBlocksLeft: No more blocks left in buffer (buffer size = %u and buffer align = %u)"};
   217      
   218        /*! 
   219         *  Maximum runtime entries 
   220         *
   221         *  Maximum number of HeapMultiBufMP's that can be dynamically created and
   222         *  added to the NameServer.
   223         *
   224         *  To minimize the amount of runtime allocation, this parameter allows
   225         *  the pre-allocation of memory for the HeapMultiBufMP's NameServer table.
   226         *  The default is to allow growth (i.e. memory allocation when 
   227         *  creating a new instance).
   228         */
   229        metaonly config UInt maxRuntimeEntries = NameServer.ALLOWGROWTH;
   230            
   231        /*! 
   232         *  Maximum length for heap names
   233         */
   234        config UInt maxNameLen = 32;
   235        
   236        /*! 
   237         *  Section name is used to place the names table
   238         *
   239         *  The default value of NULL implies that no explicit placement is 
   240         *  performed.
   241         */
   242        metaonly config String tableSection = null;
   243        
   244        /*!
   245         *  Track the maximum number of allocated blocks
   246         * 
   247         *  This will enable/disable the tracking of the maximum number of
   248         *  allocations for a HeapMultiBufMP instance.  This maximum refers to the
   249         *  "all time" maximum number of allocations for the history of a 
   250         *  HeapMultiBufMP instance, not the current number of allocations.
   251         * 
   252         *  Tracking the maximum might adversely affect performance when allocating
   253         *  and/or freeing. If this feature is not needed, setting this to false
   254         *  avoids the performance penalty.
   255         */
   256        config Bool trackMaxAllocs = false;
   257         
   258    instance:
   259    
   260        /*! 
   261         *  GateMP used for critical region management of the shared memory 
   262         *
   263         *  Using the default value of NULL will result in use of the GateMP
   264         *  system gate for context protection.
   265         */
   266        config GateMP.Handle gate = null; 
   267    
   268        /*! @_nodoc
   269         *   by the open() call. No one else should touch this!
   270         */
   271        config Bool openFlag = false;
   272        
   273        /*!
   274         *  Use exact matching
   275         *
   276         *  Setting this flag will allow allocation only if the requested size
   277         *  is equal to (rather than less than or equal to) a buffer's block size.
   278         */
   279        config Bool exact = false;
   280        
   281        /*! 
   282         *  Name of this instance.
   283         *
   284         *  The name (if not NULL) must be unique among all HeapMultiBufMP
   285         *  instances in the entire system.  When creating a new
   286         *  heap, it is necessary to supply an instance name.
   287         */
   288        config String name = null;
   289    
   290        /*!
   291         *  Number of buckets in {@link #bucketEntries}
   292         *
   293         *  This parameter is required to create any instance.
   294         */
   295        config Int numBuckets = 0;
   296        
   297        /*!
   298         *  Bucket Entries
   299         * 
   300         *  The bucket entries are an array of {@link #Bucket}s whose values  
   301         *  correspond to the desired alignment, block size and length for each 
   302         *  buffer.  It is important to note that the alignments and sizes for each 
   303         *  buffer may be adjusted due to cache and alignment related constraints.  
   304         *  Buffer sizes are rounded up by their corresponding alignments.  Buffer 
   305         *  alignments themselves will assume the value of region cache alignment 
   306         *  size when the cache size is greater than the requested buffer alignment. 
   307         * 
   308         *  For example, specifying a bucket with {blockSize: 192, align: 256} will
   309         *  result in a buffer of blockSize = 256 and alignment = 256.  If cache 
   310         *  alignment is required, then a bucket of {blockSize: 96, align: 64} will 
   311         *  result in a buffer of blockSize = 128 and alignment = 128 (assuming 
   312         *  cacheSize = 128).
   313         */
   314        config Bucket bucketEntries[];
   315        
   316        /*! 
   317         *  Shared region ID
   318         *
   319         *  The index corresponding to the shared region from which shared memory
   320         *  will be allocated.
   321         */
   322        config UInt16 regionId = 0;
   323    
   324        /*! @_nodoc
   325         *  Physical address of the shared memory
   326         *
   327         *  This value can be left as 'null' unless it is required to place the
   328         *  heap at a specific location in shared memory.  If sharedAddr is null,
   329         *  then shared memory for a new instance will be allocated from the 
   330         *  heap belonging to the region identified by {@link #regionId}.
   331         */
   332        config Ptr sharedAddr = null;
   333    
   334        @DirectCall
   335        override Ptr alloc(SizeT size, SizeT align, xdc.runtime.Error.Block *eb);
   336    
   337        @DirectCall
   338        override Void free(Ptr block, SizeT size);
   339    
   340    internal:
   341        
   342        /*! Used in the attrs->status field */
   343        const UInt32 CREATED = 0x05101920;
   344        
   345        /*! 
   346         *  This Params object is used for temporary storage of the
   347         *  module wide parameters that are for setting the NameServer instance.
   348         */
   349        metaonly config NameServer.Params nameSrvPrms;
   350    
   351        /*! slice and dice the buffer */
   352        Void postInit(Object *obj, Error.Block *eb);
   353        
   354        /*! 
   355         * Takes in modifiable array of bucket entries, performs an in-place sort
   356         * of the bucket entries, combines the entries as necessary, and returns
   357         * the new number of buckets in the combined entries
   358         */
   359        UInt processBuckets(Bucket *bucketEntries, Params *params, 
   360                            UInt16 regionId);
   361    
   362        /*! 
   363         * Add the block to the tail; index specifies the buffer number
   364         *
   365         * Precondition: inv obj->attrs->bucket[index]
   366         * Postcondition: wb obj->attrs->bucket[index] and wb the block
   367         */
   368        Void putTail(Object *obj, Int index, Elem *block);
   369        
   370        /*! 
   371         * Removes a block from the head and returns it; index specifies 
   372         * the buffer number. The block is invalidated before returned
   373         *
   374         * Precondition: inv obj->attrs->bucket[index]
   375         * Postcondition: wb obj->attrs->bucket[index]
   376         */
   377        Elem *getHead(Object *obj, Int index);
   378        
   379        /*! Needed for freelist */    
   380        @Opaque struct Elem {
   381            /* must be volatile for whole_program */
   382            volatile SharedRegion.SRPtr next;   
   383        };
   384        
   385        /*! Shared memory state for a single buffer. */
   386        struct BucketAttrs {
   387            SharedRegion.SRPtr  head;
   388            SharedRegion.SRPtr  tail;
   389            SharedRegion.SRPtr  baseAddr;
   390            Bits32              numFreeBlocks;
   391            Bits32              minFreeBlocks;
   392            Bits32              blockSize;
   393            Bits32              align;
   394            Bits32              numBlocks;
   395        }
   396        
   397        /*! Shared memory state for a HeapMultiBufMP instance */    
   398        struct Attrs {
   399            Bits32              status;         /* Created stamp                 */
   400            SharedRegion.SRPtr  gateMPAddr;     /* GateMP SRPtr                  */
   401            Bits32              numBuckets;     /* Number of buffers             */
   402            BucketAttrs         buckets[8]; /* Buffer attributes        */
   403            Bits16              exact;          /* 1 = exact matching, 0 = no    */     
   404        }
   405        
   406        struct Instance_State {
   407            Attrs               *attrs;         /* Shared state                  */
   408            GateMP.Handle       gate;           /* Gate for critical regions     */
   409            Ipc.ObjType         objType;        /* See enum ObjType              */
   410            Ptr                 nsKey;          /* Used to remove NS entry       */
   411            Bool                cacheEnabled;   /* Whether to do cache calls     */
   412            UInt16              regionId;       /* SharedRegion index            */
   413            SizeT               allocSize;      /* Shared memory allocated       */
   414            Char                *buf;           /* Local pointer to buf          */
   415            Bucket              bucketEntries[];/* Optimized bucketEntries       */
   416                                                /* NULL for dynamic instance     */
   417            UInt                numBuckets;     /* # of optimized entries        */
   418            Bool                exact;          /* Exact match flag              */
   419        };
   420        
   421        struct Module_State {
   422            NameServer.Handle   nameServer;
   423        };
   424    }