]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/big-data-ipc-examples.git/blob - host_linux/simple_buffer_example/host/HeapMem/src/HeapMem.c
host_linux: Add example for use case with host running linux
[processor-sdk/big-data-ipc-examples.git] / host_linux / simple_buffer_example / host / HeapMem / src / HeapMem.c
1 /*
2  *  @file   HeapMem.c
3  *
4  *  @brief      Defines HeapMem based memory allocator.
5  *
6  *  HeapMem is a heap implementation that manages variable size buffers that
7  *  can be used in a multiprocessor system with shared memory. HeapMem
8  *  manages a single buffer in shared memory from which blocks of user-
9  *  specified length are allocated and freed.
10  *
11  *  The HeapMem module uses a NameServerinstance to
12  *  store instance information when an instance is created.  The name supplied
13  *  must be unique for all HeapMem instances.
14  *
15  *  The create initializes the shared memory as needed. Once an
16  *  instance is created, an open can be performed. The
17  *  open is used to gain access to the same HeapMem instance.
18  *  Generally an instance is created on one processor and opened on the
19  *  other processor(s).
20  *
21  *  The open returns a HeapMem instance handle like the create,
22  *  however the open does not modify the shared memory.
23  *
24  *  Because HeapMem is a variable-size heap implementation, it is also used
25  *  by Shared Region to manage shared memory in each shared
26  *  region.  When any shared memory IPC instance is created in a
27  *  particular shared region, the HeapMem that manages shared memory in the
28  *  shared region allocates shared memory for the instance.
29  *
30  *
31  *
32  *  ============================================================================
33  *
34  *  Copyright (c) 2008-2017, Texas Instruments Incorporated
35  *
36  *  Redistribution and use in source and binary forms, with or without
37  *  modification, are permitted provided that the following conditions
38  *  are met:
39  *  
40  *  *  Redistributions of source code must retain the above copyright
41  *     notice, this list of conditions and the following disclaimer.
42  *  
43  *  *  Redistributions in binary form must reproduce the above copyright
44  *     notice, this list of conditions and the following disclaimer in the
45  *     documentation and/or other materials provided with the distribution.
46  *  
47  *  *  Neither the name of Texas Instruments Incorporated nor the names of
48  *     its contributors may be used to endorse or promote products derived
49  *     from this software without specific prior written permission.
50  *  
51  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
52  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
53  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
55  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
61  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  *  Contact information for paper mail:
63  *  Texas Instruments
64  *  Post Office Box 655303
65  *  Dallas, Texas 75265
66  *  Contact information: 
67  *  http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
68  *  DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
69  *  ============================================================================
70  *  
71  */
73 /* Standard headers */
74 #include <assert.h>
75 #include <string.h>
76 #include <stdlib.h>
78 /* IPC headers */
79 #include <ti/ipc/Std.h>
80 #include "Std.h"
81 #include <ti/ipc/MultiProc.h>
82 #include <SharedRegion.h>
83 #include <IGateProvider.h>
84 #include <GateMutex.h>
86 #include "List.h"
87 #include "HeapMem.h"
88 #include "Memory.h"
89 #include "Cache.h"
91 #include "_SharedRegion.h"
93 #define ENABLE_LOCAL_LOCK
95 /* Module level headers */
96 #include <_HeapMem.h>
97 /* round up the value 'size' to the next 'align' boundary */
98 #define ROUNDUP(size, align) \
99     (UInt32)(((UInt32)(size) + ((UInt32)(align) - 1)) & ~((UInt32)(align) - 1))
101 #define SYSLINK_BUILD_OPTIMIZE
103 /* =============================================================================
104  * Globals
105  * =============================================================================
106  */
107 /*!
108  *  @var    HeapMem_nameServer
109  *
110  *  @brief  Name of the reserved NameServer used for HeapMem.
111  */
112 #define HeapMem_NAMESERVER  "HeapMem"
114 /*! @brief Macro to make a correct module magic number with refCount */
115 #define HeapMem_MAKE_MAGICSTAMP(x) ((HeapMem_MODULEID << 12u) | (x))
117 /* =============================================================================
118  * Structures & Enums
119  * =============================================================================
120  */
121 /*!
122  *  @brief  Structure defining processor related information for the
123  *          module.
124  */
125 typedef struct HeapMem_ProcAttrs_tag {
126     Bool   creator;   /*!< Creatoror opener */
127     UInt16 procId;    /*!< Processor Identifier */
128     UInt32 openCount; /*!< How many times it is opened on a processor */
129 } HeapMem_ProcAttrs;
131 /* Header */
132 typedef struct HeapMem_Header_tag {
133     SharedRegion_SRPtr next;
134     /* SRPtr to next header (Header *)    */
135     Bits32             size;
136     /* Size of this segment (Memory.size) */
137 } HeapMem_Header;
139 /*! Structure of attributes in shared memory */
140 typedef struct HeapMem_Attrs_tag {
141     Bits32              status;
142     /* Module status                 */
143     SharedRegion_SRPtr  bufPtr;
144     /* Memory managed by instance    */
145     HeapMem_Header    head;
146     /* HeapMem      head */
147     SharedRegion_SRPtr  gateMPAddr;
148     /* GateMP SRPtr (shm safe)       */
149 } HeapMem_Attrs;
151 /*!
152  *  Structure for HeapMem module state
153  */
154 typedef struct HeapMem_ModuleObject {
155     UInt32                 refCount;
156     /*!< Reference count */
157     IGateProvider_Handle   localLock;
158     /*!< Handle to lock for protecting objList */
159     List_Object            objList;
160     /*!< List holding created objects */
161     HeapMem_Config       cfg;
162     /*!< Current config values */
163     HeapMem_Config       defaultCfg;
164     /*!< Default config values */
165     HeapMem_Params       defaultInstParams;
166     /*!< Default instance creation parameters */
167 } HeapMem_ModuleObject;
169 /*!
170  *  @brief  Structure for the Handle for the HeapMem.
171  */
172 typedef struct HeapMem_Obj_tag {
173     List_Elem           listElem;
174     /* Used for creating a linked list */
175     volatile HeapMem_Attrs   * attrs;
176     /* Local pointer to attrs        */
177     GateMP_Handle       gate;
178     /* Gate for critical regions     */
179     Ptr                 nsKey;
180     /* Used to remove NS entry       */
181     Bool                cacheEnabled;
182     /* Whether to do cache calls     */
183     UInt16              regionId;
184     /* SharedRegion index            */
185     UInt32              allocSize;
186     /* Shared memory allocated       */
187     Char              * buf;
188     /* Local pointer to buf          */
189     UInt32              minAlign;
190     /* Minimum alignment required    */
191     UInt32              bufSize;
192     /* Buffer Size */
193     HeapMem_ProcAttrs owner;
194     /* Processor related information for owner processor */
195     Ptr                 top;
196     /* Pointer to the top Object */
197     HeapMem_Params    params;
198     /* instance creation parameters */
199 } HeapMem_Obj;
201 /* =============================================================================
202  * Globals
203  * =============================================================================
204  */
205 #if !defined(SYSLINK_BUILD_DEBUG)
206 static
207 #endif /* if !defined(SYSLINK_BUILD_DEBUG) */
208 HeapMem_ModuleObject HeapMem_state =
210     .defaultCfg.maxNameLen            = 32u,
211     .defaultCfg.maxRunTimeEntries     = 32u,
212     .defaultInstParams.gate           = NULL,
213     .defaultInstParams.name           = NULL,
214     .defaultInstParams.regionId       = 0u,
215     .defaultInstParams.sharedAddr     = NULL,
216     .defaultInstParams.sharedBufSize  = 0,
217 };
219 /*!
220  *  @var    HeapMem_module
221  *
222  *  @brief  Pointer to the HeapMem module state.
223  */
224 #if !defined(SYSLINK_BUILD_DEBUG)
225 static
226 #endif /* if !defined(SYSLINK_BUILD_DEBUG) */
227 HeapMem_ModuleObject * HeapMem_module = &HeapMem_state;
229 /* =============================================================================
230  * Forward declaration of internal function
231  * =============================================================================
232  */
233 /*!
234  *  @brief      Creates a new instance of HeapMem module.
235  *              This is an internal function as both HeapMem_create
236  *              and HeapMem_open use the functionality.
237  *
238  *  @param      handlePtr  Return value: Handle
239  *  @param      params  Instance config-params structure.
240  *  @param      createFlag Indicates whether this is a create or open call.
241  *
242  *  @sa         HeapMem_delete,
243  *              ListMP_Params_init
244  *              ListMP_sharedMemReq
245  *              Gate_enter
246  *              Gate_leave
247  *              GateMutex_delete
248  *              NameServer_addUInt32
249  */
250 Int _HeapMem_create (      HeapMem_Handle * handlePtr,
251                        const HeapMem_Params * params,
252                              Bool               createFlag);
254 /* slice and dice the buffer */
255 Int HeapMem_postInit (HeapMem_Object * handle);
257 /* =============================================================================
258  * APIS
259  * =============================================================================
260  */
261 /* Get the default configuration for the HeapMem module. */
262 Void
263 HeapMem_getConfig (HeapMem_Config * cfgParams)
265     GT_1trace (curTrace, GT_ENTER, "HeapMem_getConfig", cfgParams);
267     GT_assert (curTrace, (cfgParams != NULL));
269 #if !defined(SYSLINK_BUILD_OPTIMIZE)
270     if (cfgParams == NULL) {
271         GT_setFailureReason (curTrace,
272                              GT_4CLASS,
273                              "HeapMem_getConfig",
274                              HeapMem_E_INVALIDARG,
275                              "Argument of type (HeapMem_Config *) passed "
276                              "is null!");
277     }
278     else {
279 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
280     if ((HeapMem_module->refCount & HeapMem_MAKE_MAGICSTAMP(0)) < 
281         HeapMem_MAKE_MAGICSTAMP(1)) {
282             memcpy (cfgParams,
283                          &HeapMem_module->defaultCfg,
284                          sizeof (HeapMem_Config));
285         }
286         else {
287             memcpy (cfgParams,
288                          &HeapMem_module->cfg,
289                          sizeof (HeapMem_Config));
290         }
291 #if !defined(SYSLINK_BUILD_OPTIMIZE)
292     }
293 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
295     GT_0trace (curTrace, GT_ENTER, "HeapMem_getConfig");
298 /* Setup the HeapMem module. */
299 Int
300 HeapMem_setup (const HeapMem_Config * cfg)
302     Int               status = HeapMem_S_SUCCESS;
303     Error_Block       eb;
304     HeapMem_Config  tmpCfg;
306     GT_1trace (curTrace, GT_ENTER, "HeapMem_setup", cfg);
307     Error_init (&eb);
309     if (cfg == NULL) {
310         HeapMem_getConfig (&tmpCfg);
311         cfg = &tmpCfg;
312     }
314     if (cfg == NULL) {
315         HeapMem_getConfig (&tmpCfg);
316         cfg = &tmpCfg;
317     }
319     /* This sets the refCount variable is not initialized, upper 16 bits is
320      * written with module Id to ensure correctness of refCount variable.
321      */
322     if((HeapMem_module->refCount & HeapMem_MAKE_MAGICSTAMP(0))
323         != HeapMem_MAKE_MAGICSTAMP(0)) {
324         HeapMem_module->refCount = HeapMem_MAKE_MAGICSTAMP(0);
325     }
326     if ( ++HeapMem_module->refCount
327         != HeapMem_MAKE_MAGICSTAMP(1u)) {
328         status = HeapMem_S_ALREADYSETUP;
329         GT_0trace (curTrace,
330                    GT_2CLASS,
331                    "HeapMem Module already initialized!");
332     }
333     else {
334 #if !defined(SYSLINK_BUILD_OPTIMIZE)
335         if (cfg->maxNameLen == 0) {
336             /*! @retval HeapMem_E_INVALIDARG cfg->maxNameLen passed is 0 */
337             status = HeapMem_E_INVALIDARG;
338             GT_setFailureReason (curTrace,
339                                  GT_4CLASS,
340                                  "HeapMem_setup",
341                                  status,
342                                  "cfg->maxNameLen passed is 0!");
343         }
344         else {
345 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
347                 /* Construct the list object */
348                 List_construct (&HeapMem_module->objList, NULL);
349                 /* Copy the cfg */
350                 memcpy ((Ptr) &HeapMem_module->cfg,
351                              (Ptr) cfg,
352                              sizeof (HeapMem_Config));
353 #ifdef ENABLE_LOCAL_LOCK
354                 /* Create a lock for protecting list object */
355                 HeapMem_module->localLock = (IGateProvider_Handle)
356                                GateMutex_create ((GateMutex_Params*)NULL, &eb);
357 #endif
358 #if !defined(SYSLINK_BUILD_OPTIMIZE)
359                 if (HeapMem_module->localLock == NULL) {
360                     /*! @retval HeapMem_E_FAIL Failed to create the localLock*/
361                     status = HeapMem_E_FAIL;
362                     GT_setFailureReason (curTrace,
363                                          GT_4CLASS,
364                                          "HeapMem_setup",
365                                          HeapMem_E_FAIL,
366                                          "Failed to create the localLock!");
367                     HeapMem_destroy ();
368                 }
369             }
370         }
371 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
372     }
374     GT_1trace (curTrace, GT_LEAVE, "HeapMem_setup", status);
376     /*! @retval HeapMem_S_SUCCESS Operation successful */
377     return status;
380 /* Function to destroy the HeapMem module. */
381 Int
382 HeapMem_destroy (void)
384     Int           status = HeapMem_S_SUCCESS;
385     List_Elem  *  elem;
387     GT_0trace (curTrace, GT_ENTER, "HeapMem_destroy");
389 #if !defined(SYSLINK_BUILD_OPTIMIZE)
390     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
391                                                 HeapMem_MAKE_MAGICSTAMP(0),
392                                                 HeapMem_MAKE_MAGICSTAMP(1))
393                       == TRUE)) {
394         /*! @retval HeapMem_E_INVALIDSTATE Module was not initialized */
395         status = HeapMem_E_INVALIDSTATE;
396         GT_setFailureReason (curTrace,
397                              GT_4CLASS,
398                              "HeapMem_destroy",
399                              status,
400                              "Module was not initialized!");
401     }
402     else {
403 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
404         if (   --HeapMem_module->refCount
405             == HeapMem_MAKE_MAGICSTAMP(0)) {
406             /* Temporarily increment refCount here. */
407            HeapMem_module->refCount = 
408                         HeapMem_MAKE_MAGICSTAMP(1);
409             /* Check if any HeapMem instances have not been deleted so far.
410              * If not, delete them.
411              */
412             List_traverse (elem, (List_Handle) &HeapMem_module->objList) {
413                 if (   (   ((HeapMem_Obj *) elem)->owner.procId
414                     == MultiProc_self ())) {
415                     status = HeapMem_delete ((HeapMem_Handle*)
416                                              &(((HeapMem_Obj *) elem)->top));
417                 }
418                 else {
419                     status = HeapMem_close ((HeapMem_Handle *)
420                                               &(((HeapMem_Obj *) elem)->top));
421                 }
422             }
424             /* Decrease the refCount */
425             HeapMem_module->refCount =
426                         HeapMem_MAKE_MAGICSTAMP(0);
428             /* Destruct the list object */
429             List_destruct (&HeapMem_module->objList);
430 #ifdef ENABLE_LOCAL_LOCK
431             /* Delete the list lock */
432             if (HeapMem_module->localLock != NULL) {
433                 status = GateMutex_delete ((GateMutex_Handle *)
434                                            &HeapMem_module->localLock);
435                 GT_assert (curTrace, (status >= 0));
436                 if (status < 0) {
437                     /* Override the status to return a HeapMem status code. */
438                     status = HeapMem_E_FAIL;
439                 }
440             }
441 #endif
442             memset (&HeapMem_module->cfg, 0, sizeof (HeapMem_Config));
443         }
444 #if !defined(SYSLINK_BUILD_OPTIMIZE)
445     }
446 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
448     GT_1trace (curTrace, GT_LEAVE, "HeapMem_destroy", status);
450     /*! @retval HeapMem_S_SUCCESS Operation successful */
451     return status;
454 /* Initialize this config-params structure with supplier-specified
455  * defaults before instance creation.
456  */
457 Void
458 HeapMem_Params_init (HeapMem_Params * params)
460     GT_1trace (curTrace, GT_ENTER, "HeapMem_Params_init", params);
462     GT_assert (curTrace, (params != NULL));
464 #if !defined(SYSLINK_BUILD_OPTIMIZE)
465     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
466                                                 HeapMem_MAKE_MAGICSTAMP(0),
467                                                 HeapMem_MAKE_MAGICSTAMP(1))
468                       == TRUE)) {
469         GT_setFailureReason (curTrace,
470                              GT_4CLASS,
471                              "HeapMem_Params_init",
472                              HeapMem_E_INVALIDSTATE,
473                              "Module was not initialized!");
474     }
475     else if (params == NULL) {
476         GT_setFailureReason (curTrace,
477                              GT_4CLASS,
478                              "HeapMem_Params_init",
479                              HeapMem_E_INVALIDARG,
480                              "Argument of type (HeapMem_Params *) is "
481                              "NULL!");
482     }
483     else {
484 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
485         memcpy (params,
486                      &(HeapMem_module->defaultInstParams),
487                      sizeof (HeapMem_Params));
488 #if !defined(SYSLINK_BUILD_OPTIMIZE)
489     }
490 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
492     GT_0trace (curTrace, GT_LEAVE, "HeapMem_Params_init");
495 /*!
496  *  @brief      Creates a new instance of HeapMem module.
497  *
498  *  @param      params  Instance config-params structure.
499  *
500  *  @sa         HeapMem_delete,
501  *              ListMP_Params_init
502  *              ListMP_sharedMemReq
503  *              Gate_enter
504  *              Gate_leave
505  *              NameServer_addUInt32
506  */
507 HeapMem_Handle
508 HeapMem_create (const HeapMem_Params * params)
510 #if !defined(SYSLINK_BUILD_OPTIMIZE)
511     Int                status = HeapMem_S_SUCCESS;
512 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
513     HeapMem_Object * handle = NULL;
514     HeapMem_Params   sparams;
516     GT_1trace (curTrace, GT_ENTER, "HeapMem_create", params);
518     GT_assert (curTrace, (params != NULL));
520 #if !defined(SYSLINK_BUILD_OPTIMIZE)
521     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
522                                                 HeapMem_MAKE_MAGICSTAMP(0),
523                                                 HeapMem_MAKE_MAGICSTAMP(1))
524                       == TRUE)) {
525         /*! @retval NULL if Module was not initialized */
526         status = HeapMem_E_INVALIDSTATE;
527         GT_setFailureReason (curTrace,
528                              GT_4CLASS,
529                              "HeapMem_create",
530                              status,
531                              "Module was not initialized!");
532     }
533     else if (params == NULL) {
534         /*! @retval NULL if params pointer passed is NULL */
535         status = HeapMem_E_INVALIDARG;
536         GT_setFailureReason (curTrace,
537                              GT_4CLASS,
538                              "HeapMem_create",
539                              status,
540                              "params pointer passed is NULL!");
541     }
542     else if (params->sharedBufSize == 0) {
543         /*! @retval HeapMem_E_INVALIDARG if Shared Buffer size cannot be 0
544          */
545         status = HeapMem_E_INVALIDARG;
546         GT_setFailureReason (curTrace,
547                              GT_4CLASS,
548                              "HeapMem_create",
549                              status,
550                              "Shared buffer size is 0!");
551     }
552     else {
553 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
554         memcpy (&sparams,
555                      (Ptr)params,
556                      sizeof (HeapMem_Params));
557 #if !defined(SYSLINK_BUILD_OPTIMIZE)
558         status =
559 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
560         _HeapMem_create ((HeapMem_Handle *) &handle, &sparams, TRUE);
561 #if !defined(SYSLINK_BUILD_OPTIMIZE)
562         if (status < 0) {
563             GT_setFailureReason (curTrace,
564                              GT_4CLASS,
565                              "HeapMem_create",
566                              status,
567                              "_HeapMem_create failed in HeapMem_create!");
568         }
569     }
570 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
572     GT_1trace (curTrace, GT_LEAVE, "HeapMem_create", handle);
574     /*! @retval Valid-Handle Operation successful*/
575     return (HeapMem_Handle) handle;
578 /* Deletes an instance of HeapMem module. */
579 Int
580 HeapMem_delete (HeapMem_Handle * handlePtr)
582     Int                status = HeapMem_S_SUCCESS;
583     HeapMem_Object * handle = NULL;
584     HeapMem_Obj    * obj    = NULL;
585     HeapMem_Params * params = NULL;
586     HeapMem_Handle * regionHeap = NULL;
587 #ifdef ENABLE_GATEMP
588     IArg               key    = 0;
589 #endif
590 #ifdef ENABLE_LOCAL_LOCK
591     IArg               key1   = 0;
592 #endif
594     GT_1trace (curTrace, GT_ENTER, "HeapMem_delete", handlePtr);
596     GT_assert (curTrace, (handlePtr != NULL));
597     GT_assert (curTrace, ((handlePtr != NULL) && (*handlePtr != NULL)));
599 #if !defined(SYSLINK_BUILD_OPTIMIZE)
600     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
601                                                 HeapMem_MAKE_MAGICSTAMP(0),
602                                                 HeapMem_MAKE_MAGICSTAMP(1))
603                       == TRUE)) {
604         status = HeapMem_E_INVALIDSTATE;
605         GT_setFailureReason (curTrace,
606                              GT_4CLASS,
607                              "HeapMem_delete",
608                              status,
609                              "Module was not initialized!");
610     }
611     else if (handlePtr == NULL) {
612         status = HeapMem_E_INVALIDARG;
613         GT_setFailureReason (curTrace,
614                              GT_4CLASS,
615                              "HeapMem_delete",
616                              status,
617                              "The parameter handlePtr i.e. pointer to handle "
618                              "passed is NULL!");
619     }
620     else if (*handlePtr == NULL) {
621         status = HeapMem_E_INVALIDARG;
622         GT_setFailureReason (curTrace,
623                              GT_4CLASS,
624                              "HeapMem_delete",
625                              status,
626                              "Handle passed is NULL!");
627     }
628     else {
629 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
630         handle = (HeapMem_Object *) (*handlePtr);
632         obj    = (HeapMem_Obj *) handle->obj;
634         if (obj != NULL) {
635 #if !defined(SYSLINK_BUILD_OPTIMIZE)
636             /* Check if we have created the HeapMem or not */
637             if (obj->owner.procId != MultiProc_self ()) {
638                 status = HeapMem_E_INVALIDSTATE;
639                 GT_setFailureReason (curTrace,
640                                  GT_4CLASS,
641                                  "HeapMem_delete",
642                                  status,
643                                  "Instance was not created on this processor!");
644              }
645              else {
646 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
647 #ifdef ENABLE_GATEMP
648                 /* Take the local lock */
649                key = GateMP_enter (obj->gate);
650 #endif
651 #if !defined(SYSLINK_BUILD_OPTIMIZE)
652                 if (obj->owner.openCount > 1) {
653                     status = HeapMem_E_INVALIDSTATE;
654                     GT_setFailureReason (curTrace,
655                                          GT_4CLASS,
656                                          "HeapMem_delete",
657                                          status,
658                                          "Unmatched open/close calls!");
659 #ifdef ENABLE_GATEMP
660                     /* Release the global lock */
661                     GateMP_leave (obj->gate, key);
662 #endif
663                 }
664                 else {
665 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
666 #ifdef ENABLE_LOCAL_LOCK
667                     /* Remove from  the local list */
668                     key1 = IGateProvider_enter (HeapMem_module->localLock);
669 #endif
670                     List_remove ((List_Handle) &HeapMem_module->objList,
671                                  &obj->listElem);
672 #ifdef ENABLE_LOCAL_LOCK
673                     IGateProvider_leave (HeapMem_module->localLock, key1);
674 #endif
676                     params = (HeapMem_Params *) &obj->params;
678                     if (EXPECT_TRUE(params->name != NULL)) {
680                         Memory_free (NULL,
681                                      obj->params.name,
682                                      strlen(obj->params.name) + 1u);
683                     }
685                     /* Set status to 'not created' */
686                     if (obj->attrs != NULL) {
687                         obj->attrs->status = 0;
688                         if (obj->cacheEnabled) {
689                             Cache_wbInv ((Ptr) obj->attrs,
690                                          sizeof (HeapMem_Attrs),
691                                          Cache_Type_ALL,
692                                          TRUE);
693                         }
694                     }
696 #ifdef ENABLE_GATEMP
697                     /* Release the shared lock */
698                    GateMP_leave (obj->gate, key);
699 #endif
701                     /* If necessary, free shared memory  if memory is internally
702                      * allocated
703                      */
704                     regionHeap = SharedRegion_getHeap (obj->regionId);
706                     if (   (regionHeap != NULL)
707                         && (obj->params.sharedAddr == NULL)
708                         && (obj->attrs != NULL)){
709                         Memory_free ((IHeap_Handle) regionHeap,
710                                      (Ptr) obj->attrs,
711                                      obj->allocSize);
712                     }
714                     /* Now free the handle */
715                     Memory_free (NULL, obj, sizeof (HeapMem_Obj));
716                     Memory_free (NULL, handle, sizeof (HeapMem_Object));
717                     *handlePtr = NULL;
718 #if !defined(SYSLINK_BUILD_OPTIMIZE)
719                 }
720             }
721 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
722         }
723         else {
724             Memory_free (NULL, handle, sizeof (HeapMem_Object));
725             *handlePtr = NULL;
726         }
727 #if !defined(SYSLINK_BUILD_OPTIMIZE)
728     }
729 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
731     GT_1trace (curTrace, GT_LEAVE, "HeapMem_delete", status);
733     return status;
736 /*  Opens a created instance of HeapMem module. */
737 Int
738 HeapMem_open (String             name,
739                 HeapMem_Handle * handlePtr)
741     Int                  status = HeapMem_S_SUCCESS;
742     SharedRegion_SRPtr   sharedShmBase = SharedRegion_INVALIDSRPTR;
743     Ptr                  sharedAddr    = NULL;
744 #ifdef ENABLE_LOCAL_LOCK
745     IArg                 key    = 0;
746 #endif
747     Bool                 doneFlag = FALSE;
748     List_Elem      *     elem     = NULL;
750     GT_2trace (curTrace, GT_ENTER, "HeapMem_open", name, handlePtr);
752     GT_assert (curTrace, (name != NULL));
753     GT_assert (curTrace, (handlePtr != NULL));
755 #if !defined(SYSLINK_BUILD_OPTIMIZE)
756     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
757                                                 HeapMem_MAKE_MAGICSTAMP(0),
758                                                 HeapMem_MAKE_MAGICSTAMP(1))
759                       == TRUE)) {
760         status = HeapMem_E_INVALIDSTATE;
761         GT_setFailureReason (curTrace,
762                              GT_4CLASS,
763                              "HeapMem_open",
764                              status,
765                              "Module was not initialized!");
766     }
767     else if (name == NULL) {
768         status = HeapMem_E_INVALIDARG;
769         GT_setFailureReason (curTrace,
770                              GT_4CLASS,
771                              "HeapMem_open",
772                              status,
773                              "name passed is NULL!");
774     }
775     else if (handlePtr == NULL) {
776         status = HeapMem_E_INVALIDARG;
777         GT_setFailureReason (curTrace,
778                              GT_4CLASS,
779                              "HeapMem_open",
780                              status,
781                              "Pointer to handle instance passed is NULL!");
782     }
783     else {
784 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
785         /* First check in the local list */
786         List_traverse (elem, (List_Handle) &HeapMem_module->objList) {
787             if (((HeapMem_Obj *) elem)->params.name != NULL) {
788                 if (strcmp (   ((HeapMem_Obj *)elem)->params.name, name)
789                                 == 0) {
790 #ifdef ENABLE_LOCAL_LOCK
791                     key = IGateProvider_enter (HeapMem_module->localLock);
792 #endif
793                     /* Check if we have created the HeapMem or not */
794                     if (   ((HeapMem_Obj *) elem)->owner.procId
795                         == MultiProc_self ()) {
796                         ((HeapMem_Obj *) elem)->owner.openCount++;
797                     }
799                     *handlePtr = (((HeapMem_Obj *) elem)->top);
800 #ifdef ENABLE_LOCAL_LOCK
801                     IGateProvider_leave (HeapMem_module->localLock, key);
802 #endif
803                     doneFlag = TRUE;
804                     break;
805                 }
806             }
807         }
809         if (EXPECT_TRUE (doneFlag == FALSE)) {
810 #if !defined(SYSLINK_BUILD_OPTIMIZE)
811             else if (EXPECT_FALSE (status < 0)) {
812                 /* Override the status to return a HeapMem status code. */
813                 status = HeapMem_E_FAIL;
814                 GT_setFailureReason (curTrace,
815                                      GT_4CLASS,
816                                      "HeapMem_open",
817                                      status,
818                                      "Failure in NameServer_get!");
819             }
820 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
821             {
822                 /* Convert from shared region pointer to local address*/
823                 sharedAddr = SharedRegion_getPtr (sharedShmBase);
824 #if !defined(SYSLINK_BUILD_OPTIMIZE)
825                 if (EXPECT_FALSE (sharedAddr == NULL)) {
826                     status = HeapMem_E_FAIL;
827                     GT_setFailureReason (curTrace,
828                                          GT_4CLASS,
829                                          "HeapMem_open",
830                                          status,
831                                          "Invalid pointer received from"
832                                          "NameServer!");
833                 }
834                 else {
835 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
836                     status = HeapMem_openByAddr (sharedAddr, handlePtr);
837 #if !defined(SYSLINK_BUILD_OPTIMIZE)
838                     if (EXPECT_FALSE (status < 0)) {
839                         GT_setFailureReason (curTrace,
840                                              GT_4CLASS,
841                                              "HeapMem_open",
842                                              status,
843                                             "Failed to open HeapMem handle!");
844                     }
845                 }
846 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
847             }
848         }
849 #if !defined(SYSLINK_BUILD_OPTIMIZE)
850     }
851 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
853     GT_1trace (curTrace, GT_LEAVE, "HeapMem_open", status);
855     return status;
858 /* Closes previously opened instance of HeapMem module. */
859 Int
860 HeapMem_close (HeapMem_Handle * handlePtr)
862     Int                status = HeapMem_S_SUCCESS;
863     HeapMem_Object * handle = NULL;
864     HeapMem_Obj    * obj    = NULL;
865 #ifdef ENABLE_LOCAL_LOCK
866     IArg               key    = 0;
867 #endif
868     GT_1trace (curTrace, GT_ENTER, "HeapMem_close", handlePtr);
870     GT_assert (curTrace, (handlePtr != NULL));
871     GT_assert (curTrace, ((handlePtr != NULL) && (*handlePtr != NULL)));
873 #if !defined(SYSLINK_BUILD_OPTIMIZE)
874     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
875                                                 HeapMem_MAKE_MAGICSTAMP(0),
876                                                 HeapMem_MAKE_MAGICSTAMP(1))
877                       == TRUE)) {
878         status = HeapMem_E_INVALIDSTATE;
879         GT_setFailureReason (curTrace,
880                              GT_4CLASS,
881                              "HeapMem_close",
882                              status,
883                              "Module was not initialized!");
884     }
885     else if (handlePtr == NULL) {
886         status = HeapMem_E_INVALIDARG;
887         GT_setFailureReason (curTrace,
888                              GT_4CLASS,
889                              "HeapMem_close",
890                              status,
891                              "The parameter handlePtr i.e. pointer to handle "
892                              "passed is NULL!");
893     }
894     else if (*handlePtr == NULL) {
895         status = HeapMem_E_INVALIDARG;
896         GT_setFailureReason (curTrace,
897                              GT_4CLASS,
898                              "HeapMem_close",
899                              status,
900                              "*handlePtr passed is NULL!");
901     }
902     else {
903 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
904         handle = (HeapMem_Object *) (*handlePtr);
905         obj    = (HeapMem_Obj *) handle->obj;
906         if (obj != NULL) {
907 #ifdef ENABLE_LOCAL_LOCK
908             key = IGateProvider_enter (HeapMem_module->localLock);
909 #endif
910             if (obj->owner.procId == MultiProc_self ()) {
911                 obj->owner.openCount--;
912             }
914             /* Check if HeapMem is opened on same processor and this is the
915              * last closure.
916              */
917             if (    (obj->owner.creator   == FALSE)
918                 &&  (obj->owner.openCount == 0)) {
919                 List_remove ((List_Handle) &HeapMem_module->objList,
920                              &obj->listElem);
922                 if (obj->gate != NULL) {
923 #ifdef ENABLE_GATEMP
924                     /* Close the  instance gate*/
925                     GateMP_close (&obj->gate);
926 #endif
927                 }
929                 /* Now free the handle */
930                 Memory_free (NULL, obj, sizeof (HeapMem_Obj));
931                 obj = NULL;
932                 Memory_free (NULL, handle, sizeof (HeapMem_Object));
933                 *handlePtr = NULL;
934             }
936 #ifdef ENABLE_LOCAL_LOCK
937             IGateProvider_leave (HeapMem_module->localLock, key);
938 #endif
939         }
940         else {
941             Memory_free (NULL, handle, sizeof (HeapMem_Object));
942             *handlePtr = NULL;
943         }
944 #if !defined(SYSLINK_BUILD_OPTIMIZE)
945     }
946 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
948     GT_1trace (curTrace, GT_LEAVE, "HeapMem_close", status);
950     return status;
953 /*
954  * NOTE:
955  * Embedded within the code for HeapMem_alloc and HeapMem_free are comments
956  * that can be used to match a shared memory reference with its required
957  * cache call.  This is done because the code for alloc and free is complex.
958  * These two-character comments indicate
959  * 1) The type of cache operation that is being performed {A, B}
960  *    A = Cache_inv
961  *    B = Cache_wbInv
962  * 2) A numerical id of the specific cache call that is performed.
963  *    1, 2, 3
964  *    For example, the comment 'A2' indicates that the corresponding cache call
965  *    is a Cache_inv operation identified by the number '2'
966  */
968 /*
969  *  ======== HeapMem_alloc ========
970  *  HeapMem is implemented such that all of the memory and blocks it works
971  *  with have an alignment that is a multiple of the minimum alignment and have
972  *  a size which is a multiple of the minAlign. Maintaining this requirement
973  *  throughout the implementation ensures that there are never any odd
974  *  alignments or odd block sizes to deal with.
975  *
976  *  Specifically:
977  *  The buffer managed by HeapMem:
978  *    1. Is aligned on a multiple of obj->minAlign
979  *    2. Has an adjusted size that is a multiple of obj->minAlign
980  *  All blocks on the freelist:
981  *    1. Are aligned on a multiple of obj->minAlign
982  *    2. Have a size that is a multiple of obj->minAlign
983  *  All allocated blocks:
984  *    1. Are aligned on a multiple of obj->minAlign
985  *    2. Have a size that is a multiple of obj->minAlign
986  *
987  */
989 /* Allocs a block */
990 Void *
991 HeapMem_alloc (HeapMem_Handle handle,
992                  UInt32           reqSize,
993                  UInt32           reqAlign)
995     HeapMem_Obj    * obj    = NULL;
996     Char             * allocAddr = NULL;
997 #ifdef ENABLE_GATEMP
998     IArg             key    = 0;
999 #endif
1000     HeapMem_Header * prevHeader;
1001     HeapMem_Header * newHeader;
1002     HeapMem_Header * curHeader;
1003     UInt32           curSize;
1004     UInt32           adjSize;
1005     UInt32           remainSize; /* free memory after allocated memory */
1006     UInt32           adjAlign;
1007     UInt32           offset;
1009     GT_3trace (curTrace, GT_ENTER, "HeapMem_alloc",
1010                handle, reqSize, reqAlign);
1012     GT_assert (curTrace, (handle != NULL));
1013     GT_assert (curTrace, (reqSize != 0u));
1015 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1016     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
1017                                                 HeapMem_MAKE_MAGICSTAMP(0),
1018                                                 HeapMem_MAKE_MAGICSTAMP(1))
1019                       == TRUE)) {
1020         GT_setFailureReason (curTrace,
1021                              GT_4CLASS,
1022                              "HeapMem_alloc",
1023                              HeapMem_E_INVALIDSTATE,
1024                              "Module was not initialized!");
1025     }
1026     else if (EXPECT_FALSE (handle == NULL)) {
1027         GT_setFailureReason (curTrace,
1028                              GT_4CLASS,
1029                              "HeapMem_alloc",
1030                              HeapMem_E_INVALIDARG,
1031                              "Invalid NULL handle pointer specified!");
1032     }
1033     else if (EXPECT_FALSE ((reqAlign & (reqAlign - 1)) != 0)) {
1034         GT_setFailureReason (curTrace,
1035                              GT_4CLASS,
1036                              "HeapMem_alloc",
1037                              HeapMem_E_MEMORY,
1038                              "Requested reqAlign is not a power of 2!");
1039     }
1040     else if (EXPECT_FALSE (reqSize == 0)) {
1041         GT_setFailureReason (curTrace,
1042                              GT_4CLASS,
1043                              "HeapMem_alloc",
1044                              HeapMem_E_INVALIDARG,
1045                              "Requested block size is zero!");
1046     }
1047     else {
1048 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1049         obj = (HeapMem_Obj *) ((HeapMem_Object *) handle)->obj;
1050         GT_assert (curTrace, (obj != NULL));
1052         adjSize = (UInt32) reqSize;
1054         /* Make size requested a multiple of obj->minAlign */
1055         if ((offset = (adjSize & (obj->minAlign - 1))) != 0) {
1056             adjSize = adjSize + (obj->minAlign - offset);
1057         }
1059         /*
1060          *  Make sure the alignment is at least as large as obj->minAlign
1061          *  Note: adjAlign must be a power of 2 (by function constraint) and
1062          *  obj->minAlign is also a power of 2,
1063          */
1064         adjAlign = reqAlign;
1065         if (adjAlign == 0) {
1066             adjAlign =  obj->minAlign;
1067         }
1069         if (adjAlign & (obj->minAlign - 1)) {
1070             /* adjAlign is less than obj->minAlign */
1071             adjAlign = obj->minAlign;
1072         }
1074         /* No need to Cache_inv Attrs- 'head' should be constant */
1075         prevHeader = (HeapMem_Header *) &obj->attrs->head;
1077 #ifdef ENABLE_GATEMP
1078         key = GateMP_enter (obj->gate);
1079 #endif
1081         /*
1082          *  The block will be allocated from curHeader. Maintain a pointer to
1083          *  prevHeader so prevHeader->next can be updated after the alloc.
1084          */
1085         if (EXPECT_FALSE (obj->cacheEnabled)) {
1086             Cache_inv (prevHeader,
1087                        sizeof (HeapMem_Header),
1088                        Cache_Type_ALL,
1089                        TRUE); /* A1 */
1090         }
1091         curHeader = (HeapMem_Header *) SharedRegion_getPtr (prevHeader->next);
1092         /* A1 */
1094         /* Loop over the free list. */
1095         while (curHeader != NULL) {
1096             /* Invalidate curHeader */
1097             if (EXPECT_FALSE (obj->cacheEnabled)) {
1098                 Cache_inv (curHeader,
1099                            sizeof (HeapMem_Header),
1100                            Cache_Type_ALL,
1101                            TRUE); /* A2 */
1102             }
1104             curSize = curHeader->size;
1106             /*
1107              *  Determine the offset from the beginning to make sure
1108              *  the alignment request is honored.
1109              */
1110             offset = (UInt32)curHeader & (adjAlign - 1);
1111             if (offset) {
1112                 offset = adjAlign - offset;
1113             }
1115             /* Internal Assert that offset is a multiple of obj->minAlign */
1116             if (((offset & (obj->minAlign - 1)) != 0)) {
1117                 GT_setFailureReason (curTrace,
1118                                      GT_4CLASS,
1119                                      "HeapMem_alloc",
1120                                      HeapMem_E_FAIL,
1121                                      "offset is not a multiple of"
1122                                      " obj->minAlign!");
1123             }
1124             else {
1125                 /* big enough? */
1126                 if (curSize >= (adjSize + offset)) {
1127                     /* Set the pointer that will be returned. Alloc from front */
1128                     allocAddr = (Char *) ((UInt32) curHeader + offset);
1130                     /*
1131                      *  Determine the remaining memory after the allocated block.
1132                      *  Note: this cannot be negative because of above comparison.
1133                      */
1134                     remainSize = curSize - adjSize - offset;
1136                     /* Internal Assert that remainSize is a multiple of
1137                      * obj->minAlign
1138                      */
1139                     if (((remainSize & (obj->minAlign - 1)) != 0)) {
1140                         allocAddr = NULL;
1141                         GT_setFailureReason (curTrace,
1142                                              GT_4CLASS,
1143                                              "HeapMem_alloc",
1144                                              HeapMem_E_FAIL,
1145                                              "remainSize is not a multiple of"
1146                                              " obj->minAlign!");
1147                         break;
1148                     }
1149                     else {
1150                         /*
1151                          *  If there is memory at the beginning (due to alignment
1152                          *  requirements), maintain it in the list.
1153                          *
1154                          *  offset and remainSize must be multiples of
1155                          *  sizeof(HeapMem_Header). Therefore the address of the newHeader
1156                          *  below must be a multiple of the sizeof(HeapMem_Header), thus
1157                          *  maintaining the requirement.
1158                          */
1159                         if (offset) {
1160                             /* Adjust the curHeader size accordingly */
1161                             curHeader->size = offset; /* B2 */
1162                             /* Cache wb at end of this if block */
1164                             /*
1165                              *  If there is remaining memory, add into the free list.
1166                              *  Note: no need to coalesce and we have HeapMem locked so
1167                              *        it is safe.
1168                              */
1169                             if (remainSize) {
1170                                 newHeader = (HeapMem_Header *)
1171                                             ((UInt32) allocAddr + adjSize);
1173                                 /* curHeader has been inv at top of 'while' loop */
1174                                 newHeader->next = curHeader->next;  /* B1 */
1175                                 newHeader->size = remainSize;       /* B1 */
1176                                 if (EXPECT_FALSE (obj->cacheEnabled)) {
1177                                     /* Writing back curHeader will cache-wait */
1178                                     Cache_wbInv (newHeader,
1179                                                  sizeof (HeapMem_Header),
1180                                                  Cache_Type_ALL,
1181                                                  FALSE); /* B1 */
1182                                 }
1184                                 curHeader->next = SharedRegion_getSRPtr
1185                                                                 (newHeader,
1186                                                                  obj->regionId);
1187                                 GT_assert (curTrace,
1188                                            (    curHeader->next
1189                                             !=  SharedRegion_INVALIDSRPTR));
1190                             }
1192                             /* Write back (and invalidate) newHeader and curHeader */
1193                             if (EXPECT_FALSE (obj->cacheEnabled)) {
1194                                 /* B2 */
1195                                 Cache_wbInv (curHeader,
1196                                              sizeof (HeapMem_Header),
1197                                              Cache_Type_ALL,
1198                                              TRUE);
1199                             }
1200                         }
1201                         else {
1202                             /*
1203                              *  If there is any remaining, link it in,
1204                              *  else point to the next free block.
1205                              *  Note: no need to coalesce and we have HeapMem locked so
1206                              *        it is safe.
1207                              */
1208                             if (remainSize) {
1209                                 newHeader = (HeapMem_Header *)
1210                                             ((UInt32) allocAddr + adjSize);
1212                                 newHeader->next  = curHeader->next; /* A2, B3  */
1213                                 newHeader->size  = remainSize;      /* B3      */
1215                                 if (EXPECT_FALSE (obj->cacheEnabled)) {
1216                                     /* Writing back prevHeader will cache-wait */
1217                                     Cache_wbInv (newHeader,
1218                                                  sizeof (HeapMem_Header),
1219                                                  Cache_Type_ALL,
1220                                                  FALSE); /* B3 */
1221                                 }
1223                                 /* B4 */
1224                                 prevHeader->next = SharedRegion_getSRPtr (newHeader,
1225                                                                           obj->regionId);
1226                             }
1227                             else {
1228                                 /* curHeader has been inv at top of 'while' loop */
1229                                 prevHeader->next = curHeader->next; /* A2, B4 */
1230                             }
1232                             if (EXPECT_FALSE (obj->cacheEnabled)) {
1233                                 /* B4 */
1234                                 Cache_wbInv (prevHeader,
1235                                              sizeof(HeapMem_Header),
1236                                              Cache_Type_ALL,
1237                                              TRUE);
1238                             }
1239                         }
1240                     }
1242                     /* Success, return the allocated memory */
1243                     break;
1245                 }
1246                 else {
1247                     prevHeader = curHeader;
1248                     curHeader = SharedRegion_getPtr (curHeader->next);
1249                 }
1250             }
1251         }
1253 #ifdef ENABLE_GATEMP
1254         GateMP_leave (obj->gate, key);
1255 #endif
1256 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1257     }
1258 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1260     GT_1trace (curTrace, GT_LEAVE, "HeapMem_alloc", allocAddr);
1262     return allocAddr;
1265 /* Frees a block */
1266 Void
1267 HeapMem_free (HeapMem_Handle   handle,
1268                 Ptr                addr,
1269                 UInt32             size)
1271 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1272     Int                status = HeapMem_S_SUCCESS;
1273 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1274     HeapMem_Obj    * obj    = NULL;
1275 #ifdef ENABLE_GATEMP
1276     IArg               key    = 0;
1277 #endif
1278     HeapMem_Header * curHeader = NULL;
1279     HeapMem_Header * newHeader = NULL;
1280     HeapMem_Header * nextHeader= NULL;
1281     SizeT              offset;
1283     GT_3trace (curTrace, GT_ENTER, "HeapMem_free", handle, addr, size);
1285     GT_assert (curTrace, (handle != NULL));
1286     GT_assert (curTrace, (addr != NULL));
1288 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1289     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
1290                                                 HeapMem_MAKE_MAGICSTAMP(0),
1291                                                 HeapMem_MAKE_MAGICSTAMP(1))
1292                       == TRUE)) {
1293         status = HeapMem_E_INVALIDSTATE;
1294         GT_setFailureReason (curTrace,
1295                              GT_4CLASS,
1296                              "HeapMem_free",
1297                              status,
1298                              "Module was not initialized!");
1299     }
1300     else if (EXPECT_FALSE (handle == NULL)) {
1301         status = HeapMem_E_INVALIDARG;
1302         GT_setFailureReason (curTrace,
1303                              GT_4CLASS,
1304                              "HeapMem_free",
1305                              status,
1306                              "Invalid NULL handle pointer specified!");
1307     }
1308     else if (EXPECT_FALSE (addr == NULL)) {
1309         status = HeapMem_E_INVALIDARG;
1310         GT_setFailureReason (curTrace,
1311                              GT_4CLASS,
1312                              "HeapMem_free",
1313                              status,
1314                              "Invalid NULL addr pointer specified!");
1315     }
1316     else {
1317 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1318         obj = (HeapMem_Obj *) ((HeapMem_Object *) handle)->obj;
1319         GT_assert (curTrace, (obj != NULL));
1320         GT_assert (curTrace, ((UInt32)addr % obj->minAlign == 0));
1322         /*
1323          * obj->attrs never changes, doesn't need Gate protection
1324          * and Cache invalidate
1325          */
1326         curHeader = (HeapMem_Header *) &(obj->attrs->head);
1328         /* Restore size to actual allocated size */
1329         offset = size & (obj->minAlign - 1);
1330         if (offset != 0) {
1331             size += obj->minAlign - offset;
1332         }
1334 #ifdef ENABLE_GATEMP
1335         key = GateMP_enter (obj->gate);
1336 #endif
1338         newHeader = (HeapMem_Header *) addr;
1340         if (EXPECT_FALSE (obj->cacheEnabled)) {
1341             /* A1 */
1342             Cache_inv (curHeader,
1343                        sizeof (HeapMem_Header),
1344                        Cache_Type_ALL,
1345                        TRUE);
1346         }
1347         nextHeader = SharedRegion_getPtr (curHeader->next);
1349 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1350         /* Make sure the entire buffer is in the range of the heap. */
1351         if (EXPECT_FALSE (!(    ((SizeT) newHeader >= (SizeT) obj->buf)
1352                             && (   (SizeT) newHeader + size
1353                                 <= (SizeT) obj->buf + obj->bufSize)))) {
1354             status = HeapMem_E_FAIL;
1355             GT_setFailureReason (curTrace,
1356                              GT_4CLASS,
1357                              "HeapMem_free",
1358                              status,
1359                              "Entire buffer is not in the range of the heap!");
1360         }
1361         else {
1362 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1363             /* Go down freelist and find right place for buf */
1364             while ((nextHeader != NULL) && (nextHeader < newHeader)) {
1365                 if (EXPECT_FALSE (obj->cacheEnabled)) {
1366                     Cache_inv (nextHeader,
1367                                sizeof(HeapMem_Header),
1368                                Cache_Type_ALL,
1369                                TRUE); /* A2 */
1370                 }
1372 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1373                 /* Make sure the addr is not in this free block */
1374                 if (EXPECT_FALSE (    (SizeT) newHeader
1375                                   < ((SizeT) nextHeader + nextHeader->size))) {
1376                     /* A2 */
1377                     status = HeapMem_E_INVALIDSTATE;
1378                     GT_setFailureReason (curTrace,
1379                                      GT_4CLASS,
1380                                      "HeapMem_free",
1381                                      status,
1382                                      "Address is in this free block");
1383                     break;
1384                 }
1385                 else {
1386 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1387                     curHeader = nextHeader;
1388                     /* A2 */
1389                     nextHeader = SharedRegion_getPtr (nextHeader->next);
1390 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1391                 }
1392 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1393             }
1395 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1396             if (EXPECT_TRUE (status >= 0)) {
1397 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1398                 /* B2 */
1399                 newHeader->next = SharedRegion_getSRPtr (nextHeader,
1400                                                          obj->regionId);
1401                 newHeader->size = size;
1403                 /* B1, A1 */
1404                 curHeader->next = SharedRegion_getSRPtr (newHeader,
1405                                                          obj->regionId);
1407                 /* Join contiguous free blocks */
1408                 if (nextHeader != NULL) {
1409                     /*
1410                      *  Verify the free size is not overlapping. Not all cases
1411                      *  are detectable, but it is worth a shot. Note: only do
1412                      *  this assert if nextHeader is non-NULL.
1413                      */
1414 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1415                     if (EXPECT_FALSE (  ((SizeT) newHeader + size)
1416                                       > (SizeT) nextHeader)) {
1417                         /* A2 */
1418                         status = HeapMem_E_INVALIDSTATE;
1419                         GT_setFailureReason (curTrace,
1420                                          GT_4CLASS,
1421                                          "HeapMem_free",
1422                                          status,
1423                                          "Free size is overlapping");
1424                     }
1425                     else {
1426 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1427                         /* Join with upper block */
1428                         if (((UInt32) newHeader + size) == (UInt32)nextHeader) {
1429                             if (EXPECT_FALSE (obj->cacheEnabled)) {
1430                                 Cache_inv (nextHeader,
1431                                            sizeof(HeapMem_Header),
1432                                            Cache_Type_ALL,
1433                                            TRUE);
1434                             }
1435                             newHeader->next = nextHeader->next; /* A2, B2 */
1436                             newHeader->size += nextHeader->size; /* A2, B2 */
1438                             /* Correct size for following Cache_wbInv. Needed
1439                              * due to another cache line fill caused by
1440                              * reading nextHeader->next
1441                              */
1442                             size += obj->minAlign;
1444                             /* Don't Cache_wbInv, this will be done later */
1445                         }
1446 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1447                     }
1448 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1449                 }
1451 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1452                 if (EXPECT_TRUE (status >= 0)) {
1453 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1454                     /*
1455                      *  Join with lower block. Make sure to check to see if not the
1456                      *  first block. No need to invalidate attrs since head shouldn't change.
1457                      */
1458                     if (   (curHeader != &obj->attrs->head)
1459                         && (    ((UInt32) curHeader + curHeader->size)
1460                             ==  (UInt32) newHeader)) {
1461                         /*
1462                          * Don't Cache_inv newHeader since newHeader has
1463                          * data that hasn't been written back yet (B2)
1464                          */
1465                         curHeader->next = newHeader->next; /* B1, B2 */
1466                         curHeader->size += newHeader->size; /* B1, B2 */
1467                     }
1469                     if (EXPECT_FALSE (obj->cacheEnabled)) {
1470                         Cache_wbInv (curHeader,
1471                                      sizeof (HeapMem_Header),
1472                                      Cache_Type_ALL,
1473                                      FALSE); /* B1 */
1474                         /*
1475                          *  Invalidate entire buffer being freed to ensure that
1476                          *  stale cache data in block isn't evicted later.
1477                          */
1478                         Cache_wbInv (newHeader,
1479                                      size,
1480                                      Cache_Type_ALL,
1481                                      TRUE);  /* B2 */
1482                     }
1483 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1484                 }
1485             }
1486         }
1487 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1488 #ifdef ENABLE_GATEMP
1489         GateMP_leave (obj->gate, key);
1490 #endif
1491 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1492     }
1493 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1495     GT_0trace (curTrace, GT_LEAVE, "HeapMem_free");
1498 /* Get memory statistics */
1499 Void
1500 HeapMem_getStats (HeapMem_Handle  handle,
1501                     Ptr               stats)
1503     HeapMem_Obj    * obj    = NULL;
1504     HeapMem_Header * curHeader = NULL;
1505     Memory_Stats     * memStats  = NULL;
1506 #ifdef ENABLE_GATEMP
1507     IArg               key       = 0;
1508 #endif
1510     GT_2trace (curTrace, GT_ENTER, "HeapMem_getStats", handle, stats);
1512     GT_assert (curTrace, (handle != NULL));
1513     GT_assert (curTrace, (stats != NULL));
1515 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1516     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
1517                                                 HeapMem_MAKE_MAGICSTAMP(0),
1518                                                 HeapMem_MAKE_MAGICSTAMP(1))
1519                       == TRUE)) {
1520         GT_setFailureReason (curTrace,
1521                              GT_4CLASS,
1522                              "HeapMem_getStats",
1523                              HeapMem_E_INVALIDARG,
1524                              "Module was not initialized!");
1525     }
1526     else if (EXPECT_FALSE (handle == NULL)) {
1527         GT_setFailureReason (curTrace,
1528                              GT_4CLASS,
1529                              "HeapMem_getStats",
1530                              HeapMem_E_INVALIDARG,
1531                              "handle passed is null!");
1532     }
1533     else if (EXPECT_FALSE (stats == NULL)) {
1534         GT_setFailureReason (curTrace,
1535                              GT_4CLASS,
1536                              "HeapMem_getStats",
1537                              HeapMem_E_INVALIDARG,
1538                              "Invalid NULL stats pointer specified!");
1539     }
1540     else {
1541 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1542         obj = (HeapMem_Obj *) ((HeapMem_Object *) handle)->obj;
1543         GT_assert (curTrace, (obj != NULL));
1545         memStats = (Memory_Stats *) stats;
1547         memStats->totalSize         = obj->bufSize;
1548         memStats->totalFreeSize     = 0;  /* determined later */
1549         memStats->largestFreeSize   = 0;  /* determined later */
1551 #ifdef ENABLE_GATEMP
1552         key = GateMP_enter(obj->gate);
1553 #endif
1555         /* Invalidate curHeader */
1556         if (EXPECT_FALSE (obj->cacheEnabled)) {
1557             Cache_inv ((Ptr) &(obj->attrs->head),
1558                        sizeof (HeapMem_Header),
1559                        Cache_Type_ALL,
1560                        TRUE);
1561         }
1563         curHeader = SharedRegion_getPtr ((SharedRegion_SRPtr)
1564                                                     obj->attrs->head.next);
1566         while (curHeader != NULL) {
1567             /* Invalidate curHeader */
1568             if (EXPECT_FALSE (obj->cacheEnabled)) {
1569                 Cache_inv (curHeader,
1570                            sizeof (HeapMem_Header),
1571                            Cache_Type_ALL,
1572                            TRUE);
1573             }
1575             memStats->totalFreeSize += curHeader->size;
1576             if (memStats->largestFreeSize < curHeader->size) {
1577                 memStats->largestFreeSize = curHeader->size;
1578             }
1579             /* This condition is required to avoid
1580              * assertions during call to SharedRegion_getPtr  because at the end
1581              * of the calculation curHeader->next  will become
1582              * SharedRegion_INVALIDSRPTR.
1583              */
1584             if (curHeader->next != SharedRegion_INVALIDSRPTR) {
1585                 curHeader = SharedRegion_getPtr ((SharedRegion_SRPtr)
1586                                                                curHeader->next);
1587             }
1588             else {
1589                 curHeader = NULL;
1590             }
1591         }
1593 #ifdef ENABLE_GATEMP
1594         GateMP_leave(obj->gate, key);
1595 #endif
1596 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1597     }
1598 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1600     GT_0trace (curTrace, GT_LEAVE, "HeapMem_getStats");
1603 /* Indicate whether the heap may block during an alloc or free call */
1604 Bool
1605 HeapMem_isBlocking (HeapMem_Handle handle)
1607     Bool isBlocking = FALSE;
1609     GT_1trace (curTrace, GT_ENTER, "Heap_isBlocking", handle);
1611     GT_assert (curTrace, (handle != NULL));
1613 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1614     if (EXPECT_FALSE (handle == NULL)) {
1615         GT_setFailureReason (curTrace,
1616                              GT_4CLASS,
1617                              "HeapMem_isBlocking",
1618                              HeapMem_E_INVALIDARG,
1619                              "handle passed is null!");
1620     }
1621     else {
1622 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1623         /* TBD: Figure out how to determine whether the gate is blocking */
1624 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1625     }
1626 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1628     GT_1trace (curTrace, GT_LEAVE, "HeapMem_isBlocking", isBlocking);
1630     return isBlocking;
1633 /* Get extended statistics */
1634 Void
1635 HeapMem_getExtendedStats (HeapMem_Handle           handle,
1636                             HeapMem_ExtendedStats  * stats)
1638     HeapMem_Obj * obj = NULL;
1640     GT_2trace (curTrace, GT_ENTER, "HeapMem_getExtendedStats", handle, stats);
1642     GT_assert (curTrace, (handle != NULL));
1643     GT_assert (curTrace, (stats != NULL));
1645 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1646     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
1647                                                 HeapMem_MAKE_MAGICSTAMP(0),
1648                                                 HeapMem_MAKE_MAGICSTAMP(1))
1649                       == TRUE)) {
1650         GT_setFailureReason (curTrace,
1651                              GT_4CLASS,
1652                              "HeapMem_getExtendedStats",
1653                              HeapMem_E_INVALIDSTATE,
1654                              "Module was not initialized!");
1655     }
1656     else if (EXPECT_FALSE (handle == NULL)) {
1657         GT_setFailureReason (curTrace,
1658                              GT_4CLASS,
1659                              "HeapMem_getExtendedStats",
1660                              HeapMem_E_INVALIDARG,
1661                              "Invalid NULL handle pointer specified!");
1662     }
1663     else if (EXPECT_FALSE (stats == NULL)) {
1664         GT_setFailureReason (curTrace,
1665                              GT_4CLASS,
1666                              "HeapMem_getExtendedStats",
1667                              HeapMem_E_INVALIDARG,
1668                              "Invalid NULL stats pointer specified!");
1669     }
1670     else {
1671 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1672         obj = (HeapMem_Obj *) ((HeapMem_Object *) handle)->obj;
1673         GT_assert (curTrace, (obj != NULL));
1675         stats->buf   = obj->buf;
1676         stats->size  = obj->bufSize;
1677 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1678     }
1679 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1681     GT_0trace (curTrace, GT_LEAVE, "HeapMem_getExtendedStats");
1684 /* Returns the shared memory size requirement for a single instance. */
1685 SizeT
1686 HeapMem_sharedMemReq (const HeapMem_Params * params)
1688     SizeT   memReq = 0;
1689     UInt32  minAlign;
1690     UInt16  regionId;
1692     GT_1trace (curTrace, GT_ENTER, "HeapMem_sharedMemReq", params);
1694 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1695     if (EXPECT_FALSE (params == NULL)) {
1696         GT_setFailureReason (curTrace,
1697                              GT_4CLASS,
1698                              "HeapMem_sharedMemReq",
1699                              HeapMem_E_INVALIDARG,
1700                              "Params pointer passed is NULL!");
1701     }
1702     else {
1703 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1704         if (params->sharedAddr == NULL) {
1705             regionId = params->regionId;
1706         }
1707         else {
1708             regionId = SharedRegion_getId(params->sharedAddr);
1709         }
1710 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1711         if (regionId == SharedRegion_INVALIDREGIONID)  {
1712             GT_setFailureReason (curTrace,
1713                                  GT_4CLASS,
1714                                  "HeapMem_sharedMemReq",
1715                                  HeapMem_E_FAIL,
1716                                  "params->sharedAddr is not in a"
1717                                  " valid SharedRegion!");
1718         }
1719         else {
1720 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1721             minAlign = sizeof (HeapMem_Header);
1722             if (SharedRegion_getCacheLineSize(regionId) > minAlign) {
1723                 minAlign = SharedRegion_getCacheLineSize (regionId);
1724             }
1726             /* Add size of HeapMem Attrs */
1727             memReq = ROUNDUP (sizeof(HeapMem_Attrs), minAlign);
1729             /* Add the buffer size */
1730             memReq += params->sharedBufSize;
1732             /* Make sure the size is a multiple of minAlign (round down) */
1733             memReq = (memReq / minAlign) * minAlign;
1734 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1735         }
1736     }
1737 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1739     GT_1trace (curTrace, GT_LEAVE, "HeapMem_sharedMemReq", memReq);
1741     return memReq;
1744 /*!
1745  *  @brief      Returns the HeapMem kernel object pointer.
1746  *
1747  *  @param      handle  Handle to previousely created/opened instance.
1748  *
1749  */
1750 Void *
1751 HeapMem_getKnlHandle (HeapMem_Handle handle)
1753     GT_1trace (curTrace, GT_ENTER, "HeapMem_getKnlHandle", handle);
1755     GT_assert (curTrace, (handle != NULL));
1757 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1758     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
1759                                                 HeapMem_MAKE_MAGICSTAMP(0),
1760                                                 HeapMem_MAKE_MAGICSTAMP(1))
1761                       == TRUE)) {
1762         /*! @retval NULL Module was not initialized */
1763         GT_setFailureReason (curTrace,
1764                              GT_4CLASS,
1765                              "HeapMem_getKnlHandle",
1766                              HeapMem_E_INVALIDSTATE,
1767                              "Module was not initialized!");
1768     }
1769     else if (EXPECT_FALSE (handle == NULL)) {
1770         /*! @retval NULL handle passed is NULL */
1771         GT_setFailureReason (curTrace,
1772                              GT_4CLASS,
1773                              "HeapMem_getKnlHandle",
1774                              HeapMem_E_INVALIDARG,
1775                              "handle passed is NULL!");
1776     }
1777     else {
1778 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1779         /* Nothing to be done for kernel-side implementation. */
1780 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1781     }
1782 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1784     GT_1trace (curTrace, GT_LEAVE, "HeapMem_getKnlHandle", handle);
1786     /*! @retval Kernel-Object-handle Operation successfully completed. */
1787     return (handle);
1790 /* HeapMem open by address */
1791 Int
1792 HeapMem_openByAddr (Ptr                sharedAddr,
1793                       HeapMem_Handle * handlePtr)
1795     Int               status   = HeapMem_S_SUCCESS;
1796     Bool              doneFlag = FALSE;
1797     HeapMem_Attrs * attrs    = NULL;
1798     List_Elem *       elem     = NULL;
1799 #ifdef ENABLE_LOCAL_LOCK
1800     IArg              key;
1801 #endif
1802     UInt16            id;
1803     HeapMem_Params  params;
1805     GT_2trace (curTrace, GT_ENTER, "HeapMem_openByAddr",
1806                sharedAddr, handlePtr);
1808     GT_assert (curTrace, (handlePtr != NULL));
1809     GT_assert (curTrace, (sharedAddr != NULL));
1811 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1812     if (EXPECT_FALSE (   Atomic_cmpmask_and_lt (&(HeapMem_module->refCount),
1813                                                 HeapMem_MAKE_MAGICSTAMP(0),
1814                                                 HeapMem_MAKE_MAGICSTAMP(1))
1815                       == TRUE)) {
1816         status = HeapMem_E_INVALIDSTATE;
1817         GT_setFailureReason (curTrace,
1818                              GT_4CLASS,
1819                              "HeapMem_openByAddr",
1820                              status,
1821                              "Module was not initialized!");
1822     }
1823     else if (EXPECT_FALSE (handlePtr == NULL)) {
1824         status = HeapMem_E_INVALIDARG;
1825         GT_setFailureReason (curTrace,
1826                              GT_4CLASS,
1827                              "HeapMem_openByAddr",
1828                              status,
1829                              "handlePtr pointer passed is NULL!");
1830     }
1831     else {
1832 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1833         /* First check in the local list */
1834         List_traverse (elem, (List_Handle) &HeapMem_module->objList) {
1835             if (((HeapMem_Obj *) elem)->params.sharedAddr == sharedAddr) {
1836 #ifdef ENABLE_LOCAL_LOCK
1837                 key = IGateProvider_enter (HeapMem_module->localLock);
1838 #endif
1839                 if (   ((HeapMem_Obj *)elem)->owner.procId
1840                     == MultiProc_self ()) {
1841                     ((HeapMem_Obj *)elem)->owner.openCount++;
1842                 }
1843 #ifdef ENABLE_LOCAL_LOCK
1844                 IGateProvider_leave (HeapMem_module->localLock, key);
1845 #endif
1846                 *handlePtr = (((HeapMem_Obj *)elem)->top);
1847                 doneFlag = TRUE;
1848                 break;
1849             }
1850         }
1852         /* If not already existing locally, create object locally for open. */
1853         if (EXPECT_FALSE (doneFlag == FALSE)) {
1854             HeapMem_Params_init(&params);
1855             params.sharedAddr = sharedAddr;
1856             attrs = (HeapMem_Attrs *) sharedAddr;
1857             id = SharedRegion_getId (sharedAddr);
1859             if (EXPECT_FALSE (SharedRegion_isCacheEnabled (id))) {
1860                 Cache_inv (attrs,
1861                            sizeof (HeapMem_Attrs),
1862                            Cache_Type_ALL,
1863                            TRUE);
1864             }
1866             if (EXPECT_FALSE (attrs->status != HeapMem_CREATED)) {
1867                 *handlePtr = NULL;
1868                 status = HeapMem_E_NOTFOUND;
1869                 /* Don't set failure reason since this is an expected
1870                  * run-time failure.
1871                  */
1872                 GT_1trace (curTrace,
1873                            GT_3CLASS,
1874                            "HeapMem Instance is not created yet at the "
1875                            "provided shared addr.\n"
1876                            "    sharedAddr [0x%x]!",
1877                            sharedAddr);
1878             }
1879             else {
1880                 status = _HeapMem_create (handlePtr, &params, FALSE);
1881 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1882                 if (EXPECT_FALSE (status < 0)) {
1883                     GT_setFailureReason (curTrace,
1884                                          GT_4CLASS,
1885                                          "HeapMem_openByAddr",
1886                                          status,
1887                                          "_HeapMem_create failed!");
1888                 }
1889 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1890             }
1891         }
1892 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1893     }
1894 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1896     GT_1trace (curTrace, GT_LEAVE, "HeapMem_openByAddr", status);
1898     return (status);
1901 /* =============================================================================
1902  * Internal function
1903  * =============================================================================
1904  */
1905 GateMP_Handle HeapMem_getGate(HeapMem_Handle handle)
1907     HeapMem_Object *  object;
1908     HeapMem_Obj    *  obj;
1910     object = (HeapMem_Object *)handle;
1911     obj = (HeapMem_Obj *)(object->obj);
1912     return(obj->gate);
1915 /* Creates a new instance of HeapMem module.
1916  * This is an internal function as both HeapMem_create
1917  * and HeapMem_open use the functionality.
1918  */
1919 Int
1920 _HeapMem_create (      HeapMem_Handle *  handlePtr,
1921                    const HeapMem_Params *  params,
1922                          Bool                createFlag)
1924     Int                 status = HeapMem_S_SUCCESS;
1925     HeapMem_Obj    *  obj    = NULL;
1926     HeapMem_Object *  handle = NULL;
1927 #ifdef ENABLE_GATEMP
1928     GateMP_Handle       gateHandle = NULL;
1929     Ptr                 localAddr = NULL;
1930     SharedRegion_SRPtr  sharedShmBase;
1931 #endif
1932 #ifdef ENABLE_LOCAL_LOCK
1933     IArg                key;
1934 #endif
1936     GT_3trace (curTrace, GT_ENTER, "_HeapMem_create",
1937                handlePtr, params, createFlag);
1939     GT_assert (curTrace, (handlePtr != NULL));
1940     GT_assert (curTrace, (params != NULL));
1942     /* No need for parameter checks, since this is an internal function. */
1944     /* Create the generic handle */
1945     handle = (HeapMem_Object *) Memory_calloc (NULL,
1946                                                  sizeof (HeapMem_Object),
1947                                                  0u,
1948                                                  NULL);
1949     *handlePtr = (HeapMem_Handle) handle;
1951 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1952     if (handle == NULL) {
1953         /*! @retval HeapMem_E_MEMORY Memory allocation failed for pointer of
1954          *          type HeapMem_Object
1955          */
1956         status = HeapMem_E_MEMORY;
1957         GT_setFailureReason (curTrace,
1958                              GT_4CLASS,
1959                              "_HeapMem_create",
1960                              status,
1961                              "Memory allocation failed for pointer"
1962                              " of type HeapMem_Object!");
1963     }
1964     else {
1965 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1966         /* Create the Heap Buf specific handle */
1967         obj = (HeapMem_Obj *) Memory_calloc (NULL,
1968                                                sizeof (HeapMem_Obj),
1969                                                0u,
1970                                                NULL);
1971 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1972         if (obj == NULL) {
1973             /*! @retval HeapMem_E_MEMORY Memory allocation failed for pointer
1974              *          of type HeapMem_Obj
1975              */
1976             status = HeapMem_E_MEMORY;
1977             GT_setFailureReason (curTrace,
1978                                  GT_4CLASS,
1979                                  "_HeapMem_create",
1980                                  status,
1981                                  "Memory allocation failed for pointer"
1982                                  " of type HeapMem_Obj");
1983         }
1984         else {
1985 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1986             handle->obj = (HeapMem_Obj *) obj ;
1987             handle->alloc = (IHeap_allocFxn) &HeapMem_alloc;
1988             handle->free  = (IHeap_freeFxn) &HeapMem_free;
1989             handle->getStats     = (IHeap_getStatsFxn) &HeapMem_getStats;
1990             handle->getKnlHandle = (IHeap_getKnlHandleFxn)
1991                                                     &HeapMem_getKnlHandle;
1992             handle->isBlocking   = (IHeap_isBlockingFxn) &HeapMem_isBlocking;
1994             obj->nsKey     = NULL;
1995             obj->allocSize = 0;
1997             /* Put in the local list */
1998 #ifdef ENABLE_LOCAL_LOCK
1999             key = IGateProvider_enter (HeapMem_module->localLock);
2000 #endif
2001             List_elemClear (&obj->listElem);
2002             List_put ((List_Handle) &HeapMem_module->objList, &obj->listElem);
2003 #ifdef ENABLE_LOCAL_LOCK
2004             IGateProvider_leave (HeapMem_module->localLock, key);
2005 #endif
2007             if (createFlag == FALSE) {
2008                 obj->owner.creator = FALSE;
2009                 obj->owner.openCount = 0u;
2010                 obj->owner.procId = MultiProc_INVALIDID;
2011                 obj->top = handle;
2013                 obj->attrs = (HeapMem_Attrs *) params->sharedAddr;
2015                 /* No need to Cache_inv- already done in openByAddr() */
2016                 obj->buf = (Char *) SharedRegion_getPtr ((SharedRegion_SRPtr)
2017                                                             obj->attrs->bufPtr);
2018                 obj->bufSize      = obj->attrs->head.size;
2019                 obj->regionId     = SharedRegion_getId (obj->buf);
2020                 GT_assert (curTrace,
2021                            (obj->regionId != SharedRegion_INVALIDSRPTR));
2022                 obj->cacheEnabled = SharedRegion_isCacheEnabled (obj->regionId);
2024                 /* Set minAlign */
2025                 obj->minAlign = sizeof (HeapMem_Header); /* 64 bits = 8 bytes */
2026                 if (    SharedRegion_getCacheLineSize (obj->regionId)
2027                     >   obj->minAlign) {
2028                     obj->minAlign = SharedRegion_getCacheLineSize (
2029                                                                 obj->regionId);
2030                 }
2032 #ifdef ENABLE_GATEMP
2033                 localAddr = SharedRegion_getPtr (obj->attrs->gateMPAddr);
2034                 status = GateMP_openByAddr (localAddr, &gateHandle);
2035 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2036                 if (status < 0) {
2037                     /* Override the status with a HeapMem status code. */
2038                     status = HeapMem_E_FAIL;
2039                     GT_setFailureReason (curTrace,
2040                                          GT_4CLASS,
2041                                          "_HeapMem_create",
2042                                          status,
2043                                          "Failed to open GateMP!");
2044                 }
2045                 else {
2046 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2047                     obj->gate = gateHandle;
2048 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2049                 }
2050 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2051 #endif
2052             }
2053             else {
2054                 /* Creating the HeapMem ... */
2055                 obj->owner.creator = TRUE;
2056                 obj->owner.openCount = 1u;
2057                 obj->owner.procId = MultiProc_self ();
2058                 obj->top = handle;
2060                 /* Creating the gate */
2061                 if (params->gate != NULL) {
2062                     obj->gate = params->gate;
2063                 }
2064 #ifdef ENABLE_GATEMP
2065                 else {
2066                     /* If no gate specified, get the default system gate */
2067                     obj->gate = GateMP_getDefaultRemote ();
2068                 }
2069 #endif
2070 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2071                 if (obj->gate == NULL) {
2072                     status = HeapMem_E_FAIL;
2073                     GT_setFailureReason (curTrace,
2074                                          GT_4CLASS,
2075                                          "_HeapMem_create",
2076                                          status,
2077                                          "GateMP is NULL!");
2078                 }
2079                 else {
2080 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2081                     obj->bufSize = params->sharedBufSize;
2083                     if (params->sharedAddr == NULL) {
2084                         /* Creating using a shared region ID */
2085                         /* It is allowed to have NULL name for an anonymous, not
2086                          * to be opened by name, heap.
2087                          */
2088                         obj->attrs = NULL; /* Will be alloced in postInit */
2089                         obj->regionId = params->regionId;
2090                     }
2091                     else {
2092                         /* Creating using sharedAddr */
2093                         obj->regionId = SharedRegion_getId (params->sharedAddr);
2095                         /* Assert that the buffer is in a valid shared
2096                          * region
2097                          */
2098 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2099                         if (obj->regionId == SharedRegion_INVALIDREGIONID) {
2100                             status = HeapMem_E_FAIL;
2101                             /*! @retval HeapMem_E_FAIL params->sharedAddr is
2102                                               not in a valid SharedRegion. */
2103                             GT_setFailureReason (curTrace,
2104                                                  GT_4CLASS,
2105                                                  "_HeapMem_create",
2106                                                  status,
2107                                                  "params->sharedAddr is not in"
2108                                                  " a valid SharedRegion!");
2109                         }
2110                         else if (  ((UInt32) params->sharedAddr
2111                                  % SharedRegion_getCacheLineSize (obj->regionId)
2112                                  != 0)) {
2113                             status = HeapMem_E_FAIL;
2114                             /*! @retval HeapMem_E_FAIL params->sharedAddr does
2115                                         not meet cache alignment constraints */
2116                             GT_setFailureReason (curTrace,
2117                                          GT_4CLASS,
2118                                          "_ListMP_create",
2119                                          status,
2120                                          "params->sharedAddr does not"
2121                                          " meet cache alignment constraints!");
2122                         }
2123                         else {
2124 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2125                             /* obj->buf will get alignment-adjusted in
2126                              * postInit
2127                              */
2128                             obj->buf = (Ptr) (  (UInt32) params->sharedAddr
2129                                               + sizeof (HeapMem_Attrs));
2130                             obj->attrs = (HeapMem_Attrs *) params->sharedAddr;
2131 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2132                         }
2133 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2134                     }
2136 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2137                     if (status >= 0) {
2138 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2139                         obj->cacheEnabled = SharedRegion_isCacheEnabled (
2140                                                                 obj->regionId);
2142                         /* Set minAlign */
2143                         obj->minAlign = sizeof (HeapMem_Header);
2144                         if (    SharedRegion_getCacheLineSize(obj->regionId)
2145                             >   obj->minAlign) {
2146                             obj->minAlign = SharedRegion_getCacheLineSize (
2147                                                                 obj->regionId);
2148                         }
2150                         status = HeapMem_postInit ((HeapMem_Object *)
2151                                                          handle);
2152 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2153                         if (EXPECT_FALSE (status < 0)) {
2154                             GT_setFailureReason (curTrace,
2155                                                  GT_4CLASS,
2156                                                  "_HeapMem_create",
2157                                                  status,
2158                                                  "HeapMem_postInit failed!");
2159                         }
2160                     }
2161                 }
2163                 if (status >= 0) {
2164 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2165                     /* Populate the params member */
2166                     memcpy ((Ptr) &obj->params,
2167                                  (Ptr) params,
2168                                  sizeof (HeapMem_Params));
2170                     /* Copy the name */
2171                     if (params->name != NULL) {
2172                         obj->params.name = (String) Memory_alloc (NULL,
2173                                             (strlen (params->name)+ 1u),
2174                                             0,
2175                                             NULL);
2177 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2178                         if (obj->params.name == NULL) {
2179                             /*! @retval HeapMem_E_MEMORY Memory allocation
2180                              *          failed for name
2181                              */
2182                             status = HeapMem_E_MEMORY;
2183                             GT_setFailureReason (curTrace,
2184                                                  GT_4CLASS,
2185                                                  "_HeapMem_create",
2186                                                  status,
2187                                                  "Memory allocation "
2188                                                  "failed for name!");
2189                         }
2190                         else {
2191 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2192                             strncpy (obj->params.name,
2193                                          params->name,
2194                                          strlen (params->name) + 1u);
2195 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2196                         }
2197 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2198                     }
2199                 }
2201 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2202             }
2203         }
2204     }
2205 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2207 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2208     if (status < 0) {
2209         if (createFlag == TRUE) {
2210             HeapMem_delete ((HeapMem_Handle *) handlePtr);
2211         }
2212         else {
2213             HeapMem_close ((HeapMem_Handle *) handlePtr);
2214         }
2215     }
2216 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2218     GT_1trace (curTrace, GT_LEAVE, "_HeapMem_create", status);
2220     /*! @retval HeapMem_S_SUCCESS Operation successful*/
2221     return status;
2224 /*
2225  *  Slice and dice the buffer up into the correct size blocks and
2226  *  add to the freelist.
2227  */
2228 Int
2229 HeapMem_postInit (HeapMem_Object * handle)
2231     Int              status     = HeapMem_S_SUCCESS;
2232     HeapMem_Obj *  obj        = NULL;
2233     HeapMem_Handle regionHeap = NULL;
2234     HeapMem_Params params;
2236     GT_0trace (curTrace, GT_LEAVE, "HeapMem_postInit");
2238     GT_assert (curTrace, (handle != NULL));
2240     /* No need for parameter checks, since this is an internal function. */
2242     obj = handle->obj;
2244     if (obj->attrs == NULL) {
2245         /* Need to allocate from the heap */
2246         HeapMem_Params_init (&params);
2247         params.regionId      = obj->regionId;
2248         params.sharedBufSize = obj->bufSize;
2249         obj->allocSize = HeapMem_sharedMemReq (&params);
2250         regionHeap = SharedRegion_getHeap (obj->regionId);
2251 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2252         if (regionHeap == NULL) {
2253             status = HeapMem_E_FAIL;
2254             GT_setFailureReason (curTrace,
2255                                  GT_4CLASS,
2256                                  "HeapMem_postInit",
2257                                  status,
2258                                  "Shared Region heap is null!");
2260         }
2261         else {
2262 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2263             obj->attrs = Memory_alloc ((IHeap_Handle) regionHeap,
2264                                        obj->allocSize,
2265                                        obj->minAlign,
2266                                        NULL);
2267 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2268             if (obj->attrs == NULL) {
2269                 status = HeapMem_E_MEMORY;
2270                 GT_setFailureReason (curTrace,
2271                                      GT_4CLASS,
2272                                      "HeapMem_postInit",
2273                                      status,
2274                                      "Failed to allocate shared memory!");
2275             }
2276             else {
2277 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2278                 obj->buf = (Ptr)((UInt32)obj->attrs + sizeof(HeapMem_Attrs));
2279 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2280             }
2281         }
2282 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2283     }
2285 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2286     if (status >= 0) {
2287 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2288         /* Round obj->buf up by obj->minAlign */
2289         obj->buf = (Ptr) ROUNDUP ((obj->buf), (obj->minAlign));
2291 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2292         if (EXPECT_FALSE (  obj->bufSize
2293                           < SharedRegion_getCacheLineSize (obj->regionId))) {
2294             status = HeapMem_E_FAIL;
2295             GT_setFailureReason (curTrace,
2296                                  GT_4CLASS,
2297                                  "HeapMem_postInit",
2298                                  status,
2299                                  "Buffer is not large enough!");
2300         }
2301         else {
2302 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2303             /* Make sure the size is a multiple of obj->minAlign */
2304             obj->bufSize = (obj->bufSize / obj->minAlign) * obj->minAlign;
2305 #ifdef ENABLE_GATEMP
2306             obj->attrs->gateMPAddr = GateMP_getSharedAddr (obj->gate);
2307 #endif
2308             obj->attrs->bufPtr     = SharedRegion_getSRPtr (obj->buf,
2309                                                             obj->regionId);
2311             /* Store computed obj->bufSize in shared mem */
2312             obj->attrs->head.size = obj->bufSize;
2314             /* Place the initial header */
2315             HeapMem_restore ((HeapMem_Handle) handle);
2317             /* Last thing, set the status */
2318             obj->attrs->status = HeapMem_CREATED;
2320             if (EXPECT_FALSE (obj->cacheEnabled)) {
2321                 Cache_wbInv ((Ptr) obj->attrs,
2322                              sizeof (HeapMem_Attrs),
2323                              Cache_Type_ALL,
2324                              TRUE);
2325             }
2326 #if !defined(SYSLINK_BUILD_OPTIMIZE)
2327         }
2328     }
2329 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
2331     GT_1trace (curTrace, GT_LEAVE, "HeapMem_postInit", status);
2333     return status;
2336 /* Restore an instance to it's original created state. */
2337 Void
2338 HeapMem_restore (HeapMem_Handle handle)
2340     HeapMem_Header * begHeader = NULL;
2341     HeapMem_Obj    * obj       = NULL;
2343     GT_1trace (curTrace, GT_ENTER, "HeapMem_restore", handle);
2345     obj = ((HeapMem_Object *) handle)->obj;
2346     GT_assert (curTrace, (obj != NULL));
2348     /*
2349      *  Fill in the top of the memory block
2350      *  next: pointer will be NULL (end of the list)
2351      *  size: size of this block
2352      *  NOTE: no need to Cache_inv because obj->attrs->bufPtr should be const
2353      */
2354     begHeader = (HeapMem_Header *) obj->buf;
2355     begHeader->next = (SharedRegion_SRPtr) SharedRegion_INVALIDSRPTR;
2356     begHeader->size = obj->bufSize;
2358     obj->attrs->head.next = obj->attrs->bufPtr;
2359     if (EXPECT_FALSE (obj->cacheEnabled)) {
2360         Cache_wbInv ((Ptr) &(obj->attrs->head),
2361                      sizeof (HeapMem_Header),
2362                      Cache_Type_ALL,
2363                      FALSE);
2364         Cache_wbInv (begHeader,
2365                      sizeof (HeapMem_Header),
2366                      Cache_Type_ALL,
2367                      TRUE);
2368     }
2370     GT_0trace (curTrace, GT_LEAVE, "HeapMem_restore");