1 /*
2 * Copyright (c) 2012-2019 Texas Instruments Incorporated - http://www.ti.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * ======== HeapBufMP.c ========
34 */
36 #include <xdc/std.h>
37 #include <xdc/runtime/Error.h>
38 #include <xdc/runtime/Assert.h>
39 #include <xdc/runtime/Memory.h>
40 #include <xdc/runtime/IHeap.h>
42 #include <ti/sysbios/hal/Cache.h>
44 #include <ti/sdo/ipc/_Ipc.h>
45 #include <ti/sdo/utils/_NameServer.h>
46 #include <ti/sdo/utils/_MultiProc.h>
47 #include <ti/sdo/ipc/heaps/_HeapBufMP.h>
48 #include <ti/sdo/ipc/_SharedRegion.h>
49 #include <ti/sdo/ipc/_GateMP.h>
50 #include <ti/sdo/ipc/_ListMP.h>
52 #include "package/internal/HeapBufMP.xdc.h"
54 #ifdef __ti__
55 #pragma FUNC_EXT_CALLED(HeapBufMP_Params_init);
56 #pragma FUNC_EXT_CALLED(HeapBufMP_alloc);
57 #pragma FUNC_EXT_CALLED(HeapBufMP_close);
58 #pragma FUNC_EXT_CALLED(HeapBufMP_create);
59 #pragma FUNC_EXT_CALLED(HeapBufMP_delete);
60 #pragma FUNC_EXT_CALLED(HeapBufMP_free);
61 #pragma FUNC_EXT_CALLED(HeapBufMP_getExtendedStats);
62 #pragma FUNC_EXT_CALLED(HeapBufMP_getStats);
63 #pragma FUNC_EXT_CALLED(HeapBufMP_open);
64 #pragma FUNC_EXT_CALLED(HeapBufMP_openByAddr);
65 #pragma FUNC_EXT_CALLED(HeapBufMP_sharedMemReq);
66 #endif
68 /*
69 * ======== HeapBufMP_getSharedParams ========
70 */
71 static Void HeapBufMP_getSharedParams(HeapBufMP_Params *sparams,
72 const ti_sdo_ipc_heaps_HeapBufMP_Params *params)
73 {
74 sparams->gate = (GateMP_Handle)params->gate;
75 sparams->name = params->name;
76 sparams->regionId = params->regionId;
77 sparams->sharedAddr = params->sharedAddr;
78 sparams->align = params->align;
79 sparams->numBlocks = params->numBlocks;
80 sparams->blockSize = params->blockSize;
81 sparams->exact = params->exact;
82 }
84 /*
85 * ======== HeapBufMP_getRTSCParams ========
86 */
87 static Void HeapBufMP_getRTSCParams(
88 ti_sdo_ipc_heaps_HeapBufMP_Params *params,
89 const HeapBufMP_Params *sparams)
90 {
91 ti_sdo_ipc_heaps_HeapBufMP_Params_init(params);
93 params->gate = (ti_sdo_ipc_GateMP_Handle)sparams->gate;
94 params->name = sparams->name;
95 params->regionId = sparams->regionId;
96 params->sharedAddr = sparams->sharedAddr;
97 params->align = sparams->align;
98 params->numBlocks = sparams->numBlocks;
99 params->blockSize = sparams->blockSize;
100 params->exact = sparams->exact;
101 }
103 /*
104 *************************************************************************
105 * Common Header Functions
106 *************************************************************************
107 */
109 /*
110 * ======== HeapBufMP_Params_init ========
111 */
112 Void HeapBufMP_Params_init(HeapBufMP_Params *sparams)
113 {
114 ti_sdo_ipc_heaps_HeapBufMP_Params params;
116 ti_sdo_ipc_heaps_HeapBufMP_Params_init(¶ms);
117 HeapBufMP_getSharedParams(sparams, ¶ms);
118 }
120 /*
121 * ======== HeapBufMP_alloc ========
122 */
123 Ptr HeapBufMP_alloc(HeapBufMP_Handle handle,
124 SizeT size,
125 SizeT align)
126 {
127 Error_Block eb;
129 Error_init(&eb);
131 return (ti_sdo_ipc_heaps_HeapBufMP_alloc(
132 (ti_sdo_ipc_heaps_HeapBufMP_Object *)handle, size, align, &eb));
133 }
135 /*
136 * ======== HeapBufMP_close ========
137 */
138 Int HeapBufMP_close(HeapBufMP_Handle *handlePtr)
139 {
140 HeapBufMP_delete(handlePtr);
142 return (HeapBufMP_S_SUCCESS);
143 }
145 /*
146 * ======== HeapBufMP_create ========
147 */
148 HeapBufMP_Handle HeapBufMP_create(const HeapBufMP_Params *sparams)
149 {
150 ti_sdo_ipc_heaps_HeapBufMP_Params params;
151 ti_sdo_ipc_heaps_HeapBufMP_Object *obj;
152 Error_Block eb;
154 Error_init(&eb);
156 if (sparams != NULL) {
157 HeapBufMP_getRTSCParams(¶ms, (Ptr)sparams);
159 /* call the module create */
160 obj = ti_sdo_ipc_heaps_HeapBufMP_create(¶ms, &eb);
161 }
162 else {
163 obj = ti_sdo_ipc_heaps_HeapBufMP_create(NULL, &eb);
164 }
166 return ((HeapBufMP_Handle)obj);
167 }
169 /*
170 * ======== HeapBufMP_delete ========
171 */
172 Int HeapBufMP_delete(HeapBufMP_Handle *handlePtr)
173 {
174 ti_sdo_ipc_heaps_HeapBufMP_delete(
175 (ti_sdo_ipc_heaps_HeapBufMP_Handle *)handlePtr);
177 return (HeapBufMP_S_SUCCESS);
178 }
180 /*
181 * ======== HeapBufMP_free ========
182 */
183 Void HeapBufMP_free(HeapBufMP_Handle handle, Ptr addr, SizeT size)
184 {
185 ti_sdo_ipc_heaps_HeapBufMP_free(
186 (ti_sdo_ipc_heaps_HeapBufMP_Object *)handle, addr, size);
187 }
188 /*
189 * ======== HeapBufMP_getExtendedStats ========
190 */
191 Void HeapBufMP_getExtendedStats(HeapBufMP_Handle handle,
192 HeapBufMP_ExtendedStats *stats)
193 {
194 IArg key;
195 ti_sdo_ipc_heaps_HeapBufMP_Object *obj =
196 (ti_sdo_ipc_heaps_HeapBufMP_Object *)handle;
198 key = GateMP_enter((GateMP_Handle)obj->gate);
200 /* Make sure the attrs are not in cache */
201 if (obj->cacheEnabled) {
202 Cache_inv(obj->attrs, sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs),
203 Cache_Type_ALL, TRUE);
204 }
206 /*
207 * The maximum number of allocations for this HeapBufMP (for any given
208 * instance of time during its liftime) is computed as follows:
209 *
210 * maxAllocatedBlocks = obj->numBlocks - obj->minFreeBlocks
211 *
212 * Note that maxAllocatedBlocks is *not* the maximum allocation count, but
213 * rather the maximum allocations seen at any snapshot of time in the
214 * HeapBufMP instance.
215 */
217 /* if nothing has been alloc'ed yet, return 0 */
218 if ((Int)(obj->attrs->minFreeBlocks) == -1) {
219 stats->maxAllocatedBlocks = 0;
220 }
221 else {
222 stats->maxAllocatedBlocks = obj->attrs->numBlocks -
223 obj->attrs->minFreeBlocks;
224 }
226 /* current # of alloc'ed blocks is computed using curr # of free blocks */
227 stats->numAllocatedBlocks = obj->attrs->numBlocks -
228 obj->attrs->numFreeBlocks;
230 GateMP_leave((GateMP_Handle)obj->gate, key);
231 }
233 /*
234 * ======== HeapBufMP_getStats ========
235 */
236 Void HeapBufMP_getStats(HeapBufMP_Handle handle, Ptr stats)
237 {
238 ti_sdo_ipc_heaps_HeapBufMP_getStats(
239 (ti_sdo_ipc_heaps_HeapBufMP_Handle)handle,
240 (Memory_Stats *)stats);
241 }
242 /*
243 * ======== HeapBufMP_open ========
244 */
245 Int HeapBufMP_open(String name,
246 HeapBufMP_Handle *handlePtr)
247 {
248 SharedRegion_SRPtr sharedShmBase;
249 Int status;
250 Ptr sharedAddr;
251 Error_Block eb;
253 Error_init(&eb);
255 /* Assert that a pointer has been supplied */
256 Assert_isTrue(handlePtr != NULL, ti_sdo_ipc_Ipc_A_nullArgument);
258 /* Assert that a name has been supplied */
259 Assert_isTrue(name != NULL, ti_sdo_ipc_Ipc_A_invParam);
261 /* Open by name */
262 status = NameServer_getUInt32(
263 (NameServer_Handle)HeapBufMP_module->nameServer, name,
264 &sharedShmBase, MultiProc_getClusterProcList());
266 if (status < 0) {
267 /* Name not found. */
268 *handlePtr = NULL;
269 return (HeapBufMP_E_NOTFOUND);
270 }
272 sharedAddr = SharedRegion_getPtr(sharedShmBase);
273 /* Check if sharedAddr is NULL */
274 if (sharedAddr == NULL) {
275 return (HeapBufMP_E_NOTFOUND);
276 }
278 status = HeapBufMP_openByAddr(sharedAddr, handlePtr);
280 return (status);
281 }
283 /*
284 * ======== HeapBufMP_openByAddr ========
285 */
286 Int HeapBufMP_openByAddr(Ptr sharedAddr,
287 HeapBufMP_Handle *handlePtr)
288 {
289 ti_sdo_ipc_heaps_HeapBufMP_Params params;
290 ti_sdo_ipc_heaps_HeapBufMP_Attrs *attrs;
291 Int status;
292 Error_Block eb;
294 Error_init(&eb);
296 ti_sdo_ipc_heaps_HeapBufMP_Params_init(¶ms);
298 /* Tell Instance_init() that we're opening */
299 params.openFlag = TRUE;
301 params.sharedAddr = sharedAddr;
302 attrs = (ti_sdo_ipc_heaps_HeapBufMP_Attrs *)sharedAddr;
304 if (SharedRegion_isCacheEnabled(SharedRegion_getId(sharedAddr))) {
305 Cache_inv(attrs, sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs),
306 Cache_Type_ALL, TRUE);
307 }
309 if (attrs->status != ti_sdo_ipc_heaps_HeapBufMP_CREATED) {
310 *handlePtr = NULL;
311 status = HeapBufMP_E_NOTFOUND;
312 }
313 else {
314 *handlePtr = (HeapBufMP_Handle)
315 ti_sdo_ipc_heaps_HeapBufMP_create(¶ms, &eb);
316 if (*handlePtr == NULL) {
317 status = HeapBufMP_E_FAIL;
318 }
319 else {
320 status = HeapBufMP_S_SUCCESS;
321 }
322 }
324 return (status);
325 }
327 /*
328 * ======== HeapBufMP_sharedMemReq ========
329 */
330 SizeT HeapBufMP_sharedMemReq(const HeapBufMP_Params *params)
331 {
332 SizeT memReq, minAlign, bufAlign, blockSize;
333 ListMP_Params listMPParams;
334 UInt16 regionId;
336 /* Assert that the required params have been set */
337 Assert_isTrue(params->blockSize != 0, ti_sdo_ipc_Ipc_A_invParam);
338 Assert_isTrue(params->numBlocks != 0, ti_sdo_ipc_Ipc_A_invParam);
340 if (params->sharedAddr == NULL) {
341 regionId = params->regionId;
342 }
343 else {
344 regionId = SharedRegion_getId(params->sharedAddr);
345 }
347 Assert_isTrue(regionId != SharedRegion_INVALIDREGIONID,
348 ti_sdo_ipc_Ipc_A_internal);
350 /* Determine the actual buffer alignment */
351 bufAlign = params->align;
353 minAlign = Memory_getMaxDefaultTypeAlign();
354 if (SharedRegion_getCacheLineSize(regionId) > minAlign) {
355 minAlign = SharedRegion_getCacheLineSize(regionId);
356 }
358 if (bufAlign < minAlign) {
359 bufAlign = minAlign;
360 }
362 /* Determine the actual block size */
363 blockSize = _Ipc_roundup(params->blockSize, bufAlign);
365 /* Add size of HeapBufMP Attrs */
366 memReq = _Ipc_roundup(sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs), minAlign);
368 /*
369 * Add size of ListMP Attrs. No need to init params since it's not used
370 * to create.
371 */
372 ListMP_Params_init(&listMPParams);
373 listMPParams.regionId = regionId;
374 memReq += ListMP_sharedMemReq(&listMPParams);
376 /* Round by the buffer alignment */
377 memReq = _Ipc_roundup(memReq, bufAlign);
379 /*
380 * Add the buffer size. No need to subsequently round because the product
381 * should be a multiple of cacheLineSize if cache alignment is enabled
382 */
383 memReq += blockSize * params->numBlocks;
385 return(memReq);
386 }
388 /*
389 *************************************************************************
390 * Instance functions
391 *************************************************************************
392 */
394 /*
395 * ======== ti_sdo_ipc_heaps_HeapBufMP_Instance_init ========
396 */
397 Int ti_sdo_ipc_heaps_HeapBufMP_Instance_init(
398 ti_sdo_ipc_heaps_HeapBufMP_Object *obj,
399 const ti_sdo_ipc_heaps_HeapBufMP_Params *params,
400 Error_Block *eb)
401 {
402 SharedRegion_SRPtr sharedShmBase;
403 Ptr localAddr;
404 SizeT minAlign;
405 Int status;
407 Assert_isTrue(params->openFlag ||
408 params->blockSize != 0, ti_sdo_ipc_Ipc_A_invParam);
410 obj->nsKey = NULL;
411 obj->allocSize = 0;
413 if (params->openFlag) {
414 /* Opening the gate */
415 obj->attrs =
416 (ti_sdo_ipc_heaps_HeapBufMP_Attrs *)params->sharedAddr;
418 /* No need to Cache_inv attrs- already done in openByAddr() */
419 obj->align = obj->attrs->align;
420 obj->numBlocks = obj->attrs->numBlocks;
421 obj->blockSize = obj->attrs->blockSize;
422 obj->exact = obj->attrs->exact;
423 obj->buf = SharedRegion_getPtr(obj->attrs->bufPtr);
424 obj->regionId = SharedRegion_getId(obj->buf);
426 minAlign = Memory_getMaxDefaultTypeAlign();
427 if (SharedRegion_getCacheLineSize(obj->regionId) > minAlign) {
428 minAlign = SharedRegion_getCacheLineSize(obj->regionId);
429 }
431 obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
432 obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC;
434 localAddr = SharedRegion_getPtr(obj->attrs->gateMPAddr);
436 if (localAddr == NULL) {
437 Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
438 return (4);
439 }
441 status = GateMP_openByAddr(localAddr, (GateMP_Handle *)&(obj->gate));
442 if (status != GateMP_S_SUCCESS) {
443 Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
444 return (1);
445 }
447 /* Open the ListMP */
448 localAddr = (Ptr)_Ipc_roundup(
449 (UInt32)obj->attrs + sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs),
450 minAlign);
451 status = ListMP_openByAddr(localAddr,
452 (ListMP_Handle *)&(obj->freeList));
454 if (status != ListMP_S_SUCCESS) {
455 /* obj->freeList set to NULL */
456 Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
457 return (2);
458 }
460 /* Done opening */
461 return (0);
462 }
464 /* Creating the gate */
465 if (params->gate != NULL) {
466 obj->gate = params->gate;
467 }
468 else {
469 /* If no gate specified, get the default system gate */
470 obj->gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
471 }
473 obj->exact = params->exact;
474 obj->align = params->align;
475 obj->numBlocks = params->numBlocks;
477 if (params->sharedAddr == NULL) {
478 /* Creating using a shared region ID */
479 obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION;
480 obj->attrs = NULL; /* Will be alloc'ed in postInit */
481 obj->regionId = params->regionId;
482 }
483 else {
484 /* Creating using sharedAddr */
485 obj->regionId = SharedRegion_getId(params->sharedAddr);
487 /* Assert that the buffer is in a valid shared region */
488 Assert_isTrue(obj->regionId != SharedRegion_INVALIDREGIONID,
489 ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
491 /* Assert that sharedAddr is cached aligned if region requires align. */
492 Assert_isTrue(((UInt32)params->sharedAddr %
493 SharedRegion_getCacheLineSize(obj->regionId) == 0),
494 ti_sdo_ipc_Ipc_A_addrNotCacheAligned);
496 obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC;
497 obj->attrs = (ti_sdo_ipc_heaps_HeapBufMP_Attrs *)
498 params->sharedAddr;
499 }
501 obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
503 /* Fix the alignment (alignment may be needed even if cache is disabled) */
504 obj->align = Memory_getMaxDefaultTypeAlign();
505 if (SharedRegion_getCacheLineSize(obj->regionId) > obj->align) {
506 obj->align = SharedRegion_getCacheLineSize(obj->regionId);
507 }
509 /* Round the blockSize up by the adjusted alignment */
510 obj->blockSize = _Ipc_roundup(params->blockSize, obj->align);
512 HeapBufMP_postInit(obj, eb);
513 if (Error_check(eb)) {
514 return(2);
515 }
517 /* Add entry to NameServer */
518 if (params->name != NULL) {
519 /* We will store a shared pointer in the NameServer */
520 sharedShmBase = SharedRegion_getSRPtr(obj->attrs,
521 obj->regionId);
522 obj->nsKey = NameServer_addUInt32((NameServer_Handle)
523 HeapBufMP_module->nameServer, params->name,
524 (UInt32)sharedShmBase);
526 if (obj->nsKey == NULL) {
527 /* NameServer_addUInt32 failed */
528 Error_raise(eb, ti_sdo_ipc_Ipc_E_nameFailed, params->name, 0);
529 return (3);
530 }
531 }
533 return(0);
534 }
536 /*
537 * ======== ti_sdo_ipc_heaps_HeapBufMP_Instance_finalize ========
538 */
539 Void ti_sdo_ipc_heaps_HeapBufMP_Instance_finalize(
540 ti_sdo_ipc_heaps_HeapBufMP_Object *obj, Int status)
541 {
542 if (obj->objType & (ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC |
543 ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION)) {
544 /* Heap is being deleted */
545 /* Remove entry from NameServer */
546 if (obj->nsKey != NULL) {
547 NameServer_removeEntry((NameServer_Handle)
548 HeapBufMP_module->nameServer, obj->nsKey);
549 }
551 if (obj->attrs != NULL) {
552 /* Set status to 'not created' */
553 obj->attrs->status = 0;
554 if (obj->cacheEnabled) {
555 Cache_wbInv(obj->attrs,
556 sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs),
557 Cache_Type_ALL, TRUE);
558 }
559 }
561 /* Delete the freeList. If NULL, then ListMP_create failed. */
562 if (obj->freeList != NULL) {
563 ListMP_delete((ListMP_Handle *)&(obj->freeList));
564 }
566 /*
567 * Free the shared memory back to the region heap. If NULL, then the
568 * Memory_alloc failed.
569 */
570 if (obj->objType == ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION &&
571 obj->attrs != NULL) {
572 Memory_free(SharedRegion_getHeap(obj->regionId), obj->attrs,
573 obj->allocSize);
574 }
575 }
576 else {
577 /* Heap is being closed */
578 /* Close the freeList. If NULL, then ListMP_openByAddr failed. */
579 if (obj->freeList != NULL) {
580 ListMP_close((ListMP_Handle *)&(obj->freeList));
581 }
583 /* Close the gate. If NULL, then GateMP_openByAddr failed. */
584 if (obj->gate != NULL) {
585 GateMP_close((GateMP_Handle *)&(obj->gate));
586 }
587 }
588 }
590 /*
591 * ======== ti_sdo_ipc_heaps_HeapBufMP_alloc ========
592 * Allocate a block.
593 */
594 Ptr ti_sdo_ipc_heaps_HeapBufMP_alloc(ti_sdo_ipc_heaps_HeapBufMP_Object *obj,
595 SizeT size, SizeT align, Error_Block *eb)
596 {
597 Char *block;
598 IArg key;
600 /* Check for valid blockSize */
601 if (size > obj->blockSize) {
602 Error_raise(eb, ti_sdo_ipc_heaps_HeapBufMP_E_sizeTooLarge, (IArg)size,
603 (IArg)obj->blockSize);
604 return (NULL);
605 }
607 /* Check for exact matching */
608 if (obj->exact && size != obj->blockSize) {
609 Error_raise(eb, ti_sdo_ipc_heaps_HeapBufMP_E_exactFail, (IArg)size,
610 (IArg)obj->blockSize);
611 return (NULL);
612 }
614 /* Check for valid alignment */
615 if (align > obj->align) {
616 Error_raise(eb, ti_sdo_ipc_heaps_HeapBufMP_E_alignTooLarge, (IArg)align,
617 (IArg)obj->align);
618 return (NULL);
619 }
621 /* Enter the gate */
622 key = GateMP_enter((GateMP_Handle)obj->gate);
624 /* Get the first block */
625 block = ListMP_getHead((ListMP_Handle)obj->freeList);
627 /* Make sure that a valid pointer was returned. */
628 if (block == NULL) {
629 GateMP_leave((GateMP_Handle)obj->gate, key);
630 Error_raise(eb, ti_sdo_ipc_heaps_HeapBufMP_E_noBlocksLeft, (IArg)obj,
631 (IArg)size);
633 return (NULL);
634 }
636 /*
637 * Keep track of the min number of free for this HeapBufMP, if user
638 * has set the config variable trackMaxAllocs to true. Also, keep track
639 * of the number of free blocks.
640 *
641 * The min number of free blocks, 'minFreeBlocks', will be used to compute
642 * the "all time" maximum number of allocated blocks in getExtendedStats().
643 */
644 if (ti_sdo_ipc_heaps_HeapBufMP_trackAllocs) {
645 /* Make sure the attrs are not in cache */
646 if (obj->cacheEnabled) {
647 Cache_inv(obj->attrs, sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs),
648 Cache_Type_ALL, TRUE);
649 }
651 obj->attrs->numFreeBlocks--;
653 if (obj->attrs->numFreeBlocks < obj->attrs->minFreeBlocks) {
654 /* save the new minimum */
655 obj->attrs->minFreeBlocks = obj->attrs->numFreeBlocks;
656 }
658 /* Make sure the attrs are written out to memory */
659 if (obj->cacheEnabled) {
660 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs),
661 Cache_Type_ALL, TRUE);
662 }
663 }
665 /* Leave the gate */
666 GateMP_leave((GateMP_Handle)obj->gate, key);
668 return (block);
669 }
671 /*
672 * ======== ti_sdo_ipc_heaps_HeapBufMP_free ========
673 * Frees the block to this HeapBufMP. 'size' not check for optimization
674 */
675 Void ti_sdo_ipc_heaps_HeapBufMP_free(ti_sdo_ipc_heaps_HeapBufMP_Object *obj,
676 Ptr block, SizeT size)
677 {
678 IArg key;
680 Assert_isTrue(((UInt32)block >= (UInt32)obj->buf) &&
681 ((UInt32)block < ((UInt32)obj->buf + obj->blockSize * obj->numBlocks)),
682 ti_sdo_ipc_heaps_HeapBufMP_A_invBlockFreed);
684 /* Assert that 'addr' is block-aligned */
685 Assert_isTrue((UInt32)block % obj->align == 0,
686 ti_sdo_ipc_heaps_HeapBufMP_A_badAlignment);
688 /*
689 * Invalidate entire block make sure stale cache data isn't
690 * evicted later
691 */
692 if (obj->cacheEnabled) {
693 Cache_inv(block, obj->attrs->blockSize, Cache_Type_ALL, FALSE);
694 }
696 /* Enter the gate */
697 key = GateMP_enter((GateMP_Handle)obj->gate);
699 ListMP_putTail((ListMP_Handle)obj->freeList, block);
701 if (ti_sdo_ipc_heaps_HeapBufMP_trackAllocs) {
702 /* Make sure the attrs are not in cache */
703 if (obj->cacheEnabled) {
704 Cache_inv(obj->attrs, sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs),
705 Cache_Type_ALL, FALSE);
706 }
708 obj->attrs->numFreeBlocks++;
710 /* Make sure the attrs are written out to memory */
711 if (obj->cacheEnabled) {
712 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs),
713 Cache_Type_ALL, TRUE);
714 }
715 }
717 /* Leave the gate */
718 GateMP_leave((GateMP_Handle)obj->gate, key);
719 }
721 /*
722 * ======== ti_sdo_ipc_heaps_HeapBufMP_getStats ========
723 */
724 Void ti_sdo_ipc_heaps_HeapBufMP_getStats(ti_sdo_ipc_heaps_HeapBufMP_Object *obj,
725 Memory_Stats *stats)
726 {
727 IArg key;
728 SizeT blockSize;
730 /* This is read-only, so do not need cache management */
731 blockSize = obj->attrs->blockSize;
733 /* Total size is constant */
734 stats->totalSize = blockSize * obj->attrs->numBlocks;
736 if (ti_sdo_ipc_heaps_HeapBufMP_trackAllocs) {
737 /*
738 * Protect this section so that numFreeBlocks doesn't change
739 * between totalFreeSize and largestFreeSize
740 */
741 key = GateMP_enter((GateMP_Handle)obj->gate);
742 /* Tracking enabled. Make sure the attrs are not in cache */
743 if (obj->cacheEnabled) {
744 Cache_inv(obj->attrs, sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs),
745 Cache_Type_ALL, TRUE);
746 }
748 stats->totalFreeSize = blockSize * obj->attrs->numFreeBlocks;
749 stats->largestFreeSize = (obj->attrs->numFreeBlocks > 0) ?
750 blockSize : 0;
752 GateMP_leave((GateMP_Handle)obj->gate, key);
753 }
754 else {
755 /* Tracking disabled */
756 stats->totalFreeSize = 0;
757 stats->largestFreeSize = 0;
758 }
759 }
761 /*
762 * ======== ti_sdo_ipc_heaps_HeapBufMP_isBlocking ========
763 */
764 Bool ti_sdo_ipc_heaps_HeapBufMP_isBlocking(
765 ti_sdo_ipc_heaps_HeapBufMP_Object *obj)
766 {
767 Bool flag = FALSE;
769 // TODO figure out how to determine whether the gate is blocking...
770 return (flag);
771 }
773 /*
774 *************************************************************************
775 * Internal functions
776 *************************************************************************
777 */
779 /*
780 * Shared memory Layout:
781 *
782 * sharedAddr -> ---------------------------
783 * | HeapBufMP_Attrs |
784 * | (minAlign PADDING) |
785 * |-------------------------|
786 * | ListMP shared instance |
787 * | (bufAlign PADDING) |
788 * |-------------------------|
789 * | HeapBufMP BUFFER |
790 * |-------------------------|
791 */
793 /*
794 * ======== ti_sdo_ipc_heaps_HeapBufMP_postInit ========
795 * Slice and dice the buffer up into the correct size blocks and
796 * add to the freelist.
797 */
798 Void ti_sdo_ipc_heaps_HeapBufMP_postInit(ti_sdo_ipc_heaps_HeapBufMP_Object *obj,
799 Error_Block *eb)
800 {
801 UInt i;
802 Char *buf;
803 SizeT minAlign;
804 HeapBufMP_Params heapParams;
805 ListMP_Params listMPParams;
806 IHeap_Handle regionHeap;
808 minAlign = Memory_getMaxDefaultTypeAlign();
809 if (SharedRegion_getCacheLineSize(obj->regionId) > minAlign) {
810 minAlign = SharedRegion_getCacheLineSize(obj->regionId);
811 }
813 if (obj->attrs == NULL) {
814 HeapBufMP_Params_init(&heapParams);
815 heapParams.regionId = obj->regionId;
816 heapParams.numBlocks = obj->numBlocks;
817 heapParams.align = obj->align;
818 heapParams.blockSize = obj->blockSize;
819 obj->allocSize = HeapBufMP_sharedMemReq(&heapParams);
821 regionHeap = SharedRegion_getHeap(obj->regionId);
822 Assert_isTrue(regionHeap != NULL, ti_sdo_ipc_SharedRegion_A_noHeap);
823 obj->attrs = Memory_alloc(regionHeap, obj->allocSize, minAlign, eb);
824 if (obj->attrs == NULL) {
825 return;
826 }
827 }
829 /* Store the GateMP sharedAddr in the HeapBuf Attrs */
830 obj->attrs->gateMPAddr = ti_sdo_ipc_GateMP_getSharedAddr(obj->gate);
832 /* Create the freeList */
833 ListMP_Params_init(&listMPParams);
834 listMPParams.sharedAddr = (Ptr)_Ipc_roundup((UInt32)obj->attrs +
835 sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs), minAlign);
836 listMPParams.gate = (GateMP_Handle)obj->gate;
837 obj->freeList = (ti_sdo_ipc_ListMP_Handle)ListMP_create(&listMPParams);
838 if (obj->freeList == NULL) {
839 return;
840 }
842 obj->buf = (Ptr)((SizeT)listMPParams.sharedAddr +
843 ListMP_sharedMemReq(&listMPParams));
845 obj->attrs->numFreeBlocks = obj->numBlocks;
846 obj->attrs->minFreeBlocks = (UInt)-1;
847 obj->attrs->blockSize = obj->blockSize;
848 obj->attrs->align = obj->align;
849 obj->attrs->numBlocks = obj->numBlocks;
850 obj->attrs->exact = obj->exact ? 1 : 0;
852 /* Adjust obj->buf and put a SRPtr in attrs */
853 buf = obj->buf = (Ptr)_Ipc_roundup(obj->buf, obj->align);
854 obj->attrs->bufPtr = SharedRegion_getSRPtr(obj->buf, obj->regionId);
856 /*
857 * Split the buffer into blocks that are length "blockSize" and
858 * add into the freeList Queue.
859 */
860 for (i = 0; i < obj->numBlocks; i++) {
861 /* Add the block to the freeList */
862 ListMP_putTail((ListMP_Handle)obj->freeList, (ListMP_Elem *)buf);
864 buf += obj->blockSize;
865 }
867 /* Last thing, set the status */
868 obj->attrs->status = ti_sdo_ipc_heaps_HeapBufMP_CREATED;
870 if (obj->cacheEnabled) {
871 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_heaps_HeapBufMP_Attrs),
872 Cache_Type_ALL, TRUE);
873 }
874 }