[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 =
209 {
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)
264 {
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");
296 }
298 /* Setup the HeapMem module. */
299 Int
300 HeapMem_setup (const HeapMem_Config * cfg)
301 {
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;
378 }
380 /* Function to destroy the HeapMem module. */
381 Int
382 HeapMem_destroy (void)
383 {
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;
452 }
454 /* Initialize this config-params structure with supplier-specified
455 * defaults before instance creation.
456 */
457 Void
458 HeapMem_Params_init (HeapMem_Params * params)
459 {
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");
493 }
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)
509 {
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;
576 }
578 /* Deletes an instance of HeapMem module. */
579 Int
580 HeapMem_delete (HeapMem_Handle * handlePtr)
581 {
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;
734 }
736 /* Opens a created instance of HeapMem module. */
737 Int
738 HeapMem_open (String name,
739 HeapMem_Handle * handlePtr)
740 {
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;
856 }
858 /* Closes previously opened instance of HeapMem module. */
859 Int
860 HeapMem_close (HeapMem_Handle * handlePtr)
861 {
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;
951 }
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)
994 {
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;
1263 }
1265 /* Frees a block */
1266 Void
1267 HeapMem_free (HeapMem_Handle handle,
1268 Ptr addr,
1269 UInt32 size)
1270 {
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");
1496 }
1498 /* Get memory statistics */
1499 Void
1500 HeapMem_getStats (HeapMem_Handle handle,
1501 Ptr stats)
1502 {
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");
1601 }
1603 /* Indicate whether the heap may block during an alloc or free call */
1604 Bool
1605 HeapMem_isBlocking (HeapMem_Handle handle)
1606 {
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;
1631 }
1633 /* Get extended statistics */
1634 Void
1635 HeapMem_getExtendedStats (HeapMem_Handle handle,
1636 HeapMem_ExtendedStats * stats)
1637 {
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");
1682 }
1684 /* Returns the shared memory size requirement for a single instance. */
1685 SizeT
1686 HeapMem_sharedMemReq (const HeapMem_Params * params)
1687 {
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;
1742 }
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)
1752 {
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);
1788 }
1790 /* HeapMem open by address */
1791 Int
1792 HeapMem_openByAddr (Ptr sharedAddr,
1793 HeapMem_Handle * handlePtr)
1794 {
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(¶ms);
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, ¶ms, 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);
1899 }
1901 /* =============================================================================
1902 * Internal function
1903 * =============================================================================
1904 */
1905 GateMP_Handle HeapMem_getGate(HeapMem_Handle handle)
1906 {
1907 HeapMem_Object * object;
1908 HeapMem_Obj * obj;
1910 object = (HeapMem_Object *)handle;
1911 obj = (HeapMem_Obj *)(object->obj);
1912 return(obj->gate);
1913 }
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)
1923 {
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;
2222 }
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)
2230 {
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 (¶ms);
2247 params.regionId = obj->regionId;
2248 params.sharedBufSize = obj->bufSize;
2249 obj->allocSize = HeapMem_sharedMemReq (¶ms);
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;
2334 }
2336 /* Restore an instance to it's original created state. */
2337 Void
2338 HeapMem_restore (HeapMem_Handle handle)
2339 {
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");
2371 }