d0b9e7b0432f5ea0b543fc12f40146bf0683d046
1 /*
2 * Copyright (c) 2012-2013, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * ======== ListMP.c ========
34 * Implementation of functions specified in ListMP.xdc.
35 */
37 #include <xdc/std.h>
38 #include <xdc/runtime/Error.h>
39 #include <xdc/runtime/Assert.h>
40 #include <xdc/runtime/Memory.h>
41 #include <xdc/runtime/Startup.h>
42 #include <xdc/runtime/System.h>
43 #include <xdc/runtime/IHeap.h>
45 #include <ti/sysbios/hal/Cache.h>
47 #include <ti/sdo/ipc/_Ipc.h>
48 #include <ti/sdo/utils/_MultiProc.h>
49 #include <ti/sdo/utils/_NameServer.h>
50 #include <ti/sdo/ipc/_GateMP.h>
51 #include <ti/sdo/ipc/_ListMP.h>
52 #include <ti/sdo/ipc/_SharedRegion.h>
54 #include "package/internal/ListMP.xdc.h"
57 #ifdef __ti__
58 #pragma FUNC_EXT_CALLED(ListMP_Params_init);
59 #pragma FUNC_EXT_CALLED(ListMP_create);
60 #pragma FUNC_EXT_CALLED(ListMP_close);
61 #pragma FUNC_EXT_CALLED(ListMP_delete);
62 #pragma FUNC_EXT_CALLED(ListMP_open);
63 #pragma FUNC_EXT_CALLED(ListMP_openByAddr);
64 #pragma FUNC_EXT_CALLED(ListMP_sharedMemReq);
65 #pragma FUNC_EXT_CALLED(ListMP_empty);
66 #pragma FUNC_EXT_CALLED(ListMP_getGate);
67 #pragma FUNC_EXT_CALLED(ListMP_getHead);
68 #pragma FUNC_EXT_CALLED(ListMP_getTail);
69 #pragma FUNC_EXT_CALLED(ListMP_insert);
70 #pragma FUNC_EXT_CALLED(ListMP_next);
71 #pragma FUNC_EXT_CALLED(ListMP_prev);
72 #pragma FUNC_EXT_CALLED(ListMP_putHead);
73 #pragma FUNC_EXT_CALLED(ListMP_putTail);
74 #pragma FUNC_EXT_CALLED(ListMP_remove);
75 #endif
77 /*
78 *************************************************************************
79 * Common Header Functions
80 *************************************************************************
81 */
83 /*
84 * ======== ListMP_Params_init ========
85 */
86 Void ListMP_Params_init(ListMP_Params *params)
87 {
88 /* init the params to the defaults */
89 params->gate = NULL;
90 params->sharedAddr = 0;
91 params->name = NULL;
92 params->regionId = 0;
93 }
95 /*
96 * ======== ListMP_create ========
97 */
98 ListMP_Handle ListMP_create(const ListMP_Params *params)
99 {
100 ti_sdo_ipc_ListMP_Params mpParams;
101 ti_sdo_ipc_ListMP_Object *obj;
102 Error_Block eb;
104 Error_init(&eb);
106 if (params != NULL) {
107 /* init the module params struct */
108 ti_sdo_ipc_ListMP_Params_init(&mpParams);
109 mpParams.gate = (ti_sdo_ipc_GateMP_Handle)params->gate;
110 mpParams.openFlag = FALSE;
111 mpParams.sharedAddr = params->sharedAddr;
112 mpParams.name = params->name;
113 mpParams.regionId = params->regionId;
115 /* call the module create */
116 obj = ti_sdo_ipc_ListMP_create(&mpParams, &eb);
117 }
118 else {
119 obj = ti_sdo_ipc_ListMP_create(NULL, &eb);
120 }
122 return ((ListMP_Handle)obj);
123 }
125 /*
126 * ======== ListMP_close ========
127 */
128 Int ListMP_close(ListMP_Handle *handlePtr)
129 {
130 ListMP_delete(handlePtr);
132 return (ListMP_S_SUCCESS);
133 }
135 /*
136 * ======== ListMP_delete ========
137 */
138 Int ListMP_delete(ListMP_Handle *handlePtr)
139 {
140 ti_sdo_ipc_ListMP_delete((ti_sdo_ipc_ListMP_Handle *)handlePtr);
142 return (ListMP_S_SUCCESS);
143 }
145 /*
146 * ======== ListMP_open ========
147 */
148 Int ListMP_open(String name, ListMP_Handle *handlePtr)
149 {
150 SharedRegion_SRPtr sharedShmBase;
151 Ptr sharedAddr;
152 Int status;
154 /* Assert that a pointer has been supplied */
155 Assert_isTrue(handlePtr != NULL, ti_sdo_ipc_Ipc_A_nullArgument);
157 /* Assert that we have enough information to open the gate */
158 Assert_isTrue(name != NULL, ti_sdo_ipc_Ipc_A_invParam);
160 /* Search NameServer */
161 status = NameServer_getUInt32((NameServer_Handle)ListMP_module->nameServer,
162 name,
163 &sharedShmBase,
164 ti_sdo_utils_MultiProc_procIdList);
166 if (status < 0) {
167 /* Name was not found */
168 *handlePtr = NULL;
169 return (ListMP_E_NOTFOUND);
170 }
172 sharedAddr = SharedRegion_getPtr(sharedShmBase);
174 status = ListMP_openByAddr(sharedAddr, handlePtr);
176 return (status);
177 }
179 /*
180 * ======== ListMP_openByAddr ========
181 */
182 Int ListMP_openByAddr(Ptr sharedAddr, ListMP_Handle *handlePtr)
183 {
184 ti_sdo_ipc_ListMP_Params params;
185 ti_sdo_ipc_ListMP_Attrs *attrs;
186 Error_Block eb;
187 Int status;
188 UInt16 id;
190 Error_init(&eb);
192 ti_sdo_ipc_ListMP_Params_init(¶ms);
194 /* Tell Instance_init() that we're opening */
195 params.openFlag = TRUE;
197 attrs = (ti_sdo_ipc_ListMP_Attrs *)sharedAddr;
198 params.sharedAddr = sharedAddr;
199 id = SharedRegion_getId(sharedAddr);
201 if (SharedRegion_isCacheEnabled(id)) {
202 Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
203 }
205 if (attrs->status != ti_sdo_ipc_ListMP_CREATED) {
206 *handlePtr = NULL;
207 status = ListMP_E_NOTFOUND;
208 }
209 else {
210 /* Create the object */
211 *handlePtr = (ListMP_Handle)ti_sdo_ipc_ListMP_create(¶ms, &eb);
212 if (*handlePtr == NULL) {
213 status = ListMP_E_FAIL;
214 }
215 else {
216 status = ListMP_S_SUCCESS;
217 }
218 }
220 if (SharedRegion_isCacheEnabled(id)) {
221 Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
222 }
224 return (status);
225 }
227 /*
228 * ======== ListMP_sharedMemReq ========
229 */
230 SizeT ListMP_sharedMemReq(const ListMP_Params *params)
231 {
232 SizeT memReq, minAlign;
233 UInt16 regionId;
235 if (params->sharedAddr == NULL) {
236 regionId = params->regionId;
237 }
238 else {
239 regionId = SharedRegion_getId(params->sharedAddr);
240 }
242 /* Assert that the region is valid */
243 Assert_isTrue(regionId != SharedRegion_INVALIDREGIONID,
244 ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
246 minAlign = Memory_getMaxDefaultTypeAlign();
247 if (SharedRegion_getCacheLineSize(regionId) > minAlign) {
248 minAlign = SharedRegion_getCacheLineSize(regionId);
249 }
251 memReq = _Ipc_roundup(sizeof(ti_sdo_ipc_ListMP_Attrs), minAlign);
253 return (memReq);
254 }
256 /*
257 * ======== ListMP_empty ========
258 */
259 Bool ListMP_empty(ListMP_Handle handle)
260 {
261 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
262 Bool flag = FALSE;
263 IArg key;
264 SharedRegion_SRPtr sharedHead;
266 /* prevent another thread or processor from modifying the ListMP */
267 key = GateMP_enter((GateMP_Handle)obj->gate);
270 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
271 /* get the SRPtr for the head */
272 sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head);
273 }
274 else {
275 /* get the SRPtr for the head */
276 sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId);
277 }
279 /* if 'next' is ourself, then the ListMP must be empty */
280 if (obj->attrs->head.next == sharedHead) {
281 flag = TRUE;
282 }
284 if (obj->cacheEnabled) {
285 /* invalidate the head to make sure we are not getting stale data */
286 Cache_inv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL,
287 TRUE);
288 }
290 /* leave the gate */
291 GateMP_leave((GateMP_Handle)obj->gate, key);
293 return (flag);
294 }
296 /*
297 * ======== ListMP_getGate ========
298 */
299 GateMP_Handle ListMP_getGate(ListMP_Handle handle)
300 {
301 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
303 return ((GateMP_Handle)obj->gate);
304 }
306 /*
307 * ======== ListMP_getHead ========
308 */
309 Ptr ListMP_getHead(ListMP_Handle handle)
310 {
311 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
312 ListMP_Elem *elem;
313 ListMP_Elem *localHeadNext;
314 ListMP_Elem *localNext;
315 Bool localNextIsCached;
316 UInt key;
318 /* prevent another thread or processor from modifying the ListMP */
319 key = GateMP_enter((GateMP_Handle)obj->gate);
321 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
322 localHeadNext = (ListMP_Elem *)obj->attrs->head.next;
323 }
324 else {
325 localHeadNext = SharedRegion_getPtr(obj->attrs->head.next);
326 }
328 /* Assert that pointer is not NULL */
329 Assert_isTrue(localHeadNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
331 /* See if the ListMP was empty */
332 if (localHeadNext == (ListMP_Elem *)(&(obj->attrs->head))) {
333 /* Empty, return NULL */
334 elem = NULL;
335 }
336 else {
337 if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadNext))) {
338 /* invalidate elem */
339 Cache_inv(localHeadNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
340 }
342 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
343 localNext = (ListMP_Elem *)localHeadNext->next;
344 }
345 else {
346 localNext = SharedRegion_getPtr(localHeadNext->next);
347 }
349 /* Assert that pointer is not NULL */
350 Assert_isTrue(localNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
352 /* Elem to return */
353 elem = localHeadNext;
354 localNextIsCached = SharedRegion_isCacheEnabled(
355 SharedRegion_getId(localNext));
356 if (localNextIsCached) {
357 Cache_inv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
358 }
360 /* Fix the head of the list next pointer */
361 obj->attrs->head.next = elem->next;
363 /* Fix the prev pointer of the new first elem on the list */
364 localNext->prev = localHeadNext->prev;
365 if (localNextIsCached) {
366 Cache_wbInv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
367 }
368 }
370 if (obj->cacheEnabled) {
371 Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem),
372 Cache_Type_ALL, TRUE);
373 }
375 GateMP_leave((GateMP_Handle)obj->gate, key);
377 return (elem);
378 }
380 /*
381 * ======== ListMP_getTail ========
382 */
383 Ptr ListMP_getTail(ListMP_Handle handle)
384 {
385 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
386 ListMP_Elem *elem;
387 ListMP_Elem *localHeadPrev;
388 ListMP_Elem *localPrev;
389 Bool localPrevIsCached;
390 UInt key;
392 /* prevent another thread or processor from modifying the ListMP */
393 key = GateMP_enter((GateMP_Handle)obj->gate);
395 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
396 localHeadPrev = (ListMP_Elem *)obj->attrs->head.prev;
397 }
398 else {
399 localHeadPrev = SharedRegion_getPtr(obj->attrs->head.prev);
400 }
402 /* Assert that pointer is not NULL */
403 Assert_isTrue(localHeadPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
405 /* See if the ListMP was empty */
406 if (localHeadPrev == (ListMP_Elem *)(&(obj->attrs->head))) {
407 /* Empty, return NULL */
408 elem = NULL;
409 }
410 else {
411 if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadPrev))) {
412 /* invalidate elem */
413 Cache_inv(localHeadPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
414 }
416 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
417 localPrev = (ListMP_Elem *)localHeadPrev->prev;
418 }
419 else {
420 localPrev = SharedRegion_getPtr(localHeadPrev->prev);
421 }
423 /* Assert that pointer is not NULL */
424 Assert_isTrue(localPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
426 /* Elem to return */
427 elem = localHeadPrev;
428 localPrevIsCached = SharedRegion_isCacheEnabled(
429 SharedRegion_getId(localPrev));
430 if (localPrevIsCached) {
431 Cache_inv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
432 }
434 /* Fix the head of the list prev pointer */
435 obj->attrs->head.prev = elem->prev;
437 /* Fix the next pointer of the new last elem on the list */
438 localPrev->next = localHeadPrev->next;
439 if (localPrevIsCached) {
440 Cache_wbInv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
441 }
442 }
444 if (obj->cacheEnabled) {
445 Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem),
446 Cache_Type_ALL, TRUE);
447 }
449 GateMP_leave((GateMP_Handle)obj->gate, key);
451 return (elem);
452 }
454 /*
455 * ======== ListMP_insert ========
456 */
457 Int ListMP_insert(ListMP_Handle handle, ListMP_Elem *newElem,
458 ListMP_Elem *curElem)
459 {
460 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
461 UInt key;
462 Int id;
463 ListMP_Elem *localPrevElem;
464 SharedRegion_SRPtr sharedNewElem;
465 SharedRegion_SRPtr sharedCurElem;
466 Bool curElemIsCached, localPrevElemIsCached;
468 /* prevent another thread or processor from modifying the ListMP */
469 key = GateMP_enter((GateMP_Handle)obj->gate);
471 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
472 sharedNewElem = (SharedRegion_SRPtr)newElem;
473 sharedCurElem = (SharedRegion_SRPtr)curElem;
474 localPrevElem = (ListMP_Elem *)(curElem->prev);
475 }
476 else {
477 /* get SRPtr for newElem */
478 id = SharedRegion_getId(newElem);
479 sharedNewElem = SharedRegion_getSRPtr(newElem, id);
481 /* get SRPtr for curElem */
482 id = SharedRegion_getId(curElem);
483 sharedCurElem = SharedRegion_getSRPtr(curElem, id);
484 }
486 curElemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(curElem));
487 if (curElemIsCached) {
488 Cache_inv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
489 }
491 /* get Ptr for curElem->prev */
492 localPrevElem = SharedRegion_getPtr(curElem->prev);
494 localPrevElemIsCached = SharedRegion_isCacheEnabled(
495 SharedRegion_getId(localPrevElem));
496 if (localPrevElemIsCached) {
497 Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
498 }
500 newElem->next = sharedCurElem;
501 newElem->prev = curElem->prev;
502 localPrevElem->next = sharedNewElem;
503 curElem->prev = sharedNewElem;
505 if (localPrevElemIsCached) {
506 Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
507 }
509 /*
510 * The next two Cache_wbInv needs to be done because curElem
511 * and newElem are passed in and maybe already in the cache
512 */
513 if (curElemIsCached) {
514 /* writeback invalidate current elem structure */
515 Cache_wbInv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
516 }
518 if (SharedRegion_isCacheEnabled(SharedRegion_getId(newElem))) {
519 /* writeback invalidate new elem structure */
520 Cache_wbInv(newElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
521 }
523 GateMP_leave((GateMP_Handle)obj->gate, key);
525 return (ListMP_S_SUCCESS);
526 }
528 /*
529 * ======== ListMP_next ========
530 */
531 Ptr ListMP_next(ListMP_Handle handle, ListMP_Elem *elem)
532 {
533 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
534 ListMP_Elem *retElem; /* returned elem */
535 Bool elemIsCached;
537 /* elem == NULL -> start at the head */
538 if (elem == NULL) {
539 /* Keep track of whether an extra Cache_inv is needed */
540 elemIsCached = obj->cacheEnabled;
541 elem = (ListMP_Elem *)&(obj->attrs->head);
543 }
544 else {
545 elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
546 }
548 if (elemIsCached) {
549 Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
550 }
552 retElem = SharedRegion_getPtr(elem->next);
554 if (retElem == (ListMP_Elem *)(&obj->attrs->head)) {
555 retElem = NULL;
556 }
558 if (elemIsCached) {
559 /* Invalidate because elem pulled into cache && elem != head. */
560 Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
561 }
563 return (retElem);
564 }
566 /*
567 * ======== ListMP_prev ========
568 */
569 Ptr ListMP_prev(ListMP_Handle handle, ListMP_Elem *elem)
570 {
571 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
572 ListMP_Elem *retElem; /* returned elem */
573 Bool elemIsCached;
575 /* elem == NULL -> start at the head */
576 if (elem == NULL) {
577 elemIsCached = obj->cacheEnabled;
578 elem = (ListMP_Elem *)&(obj->attrs->head);
579 }
580 else {
581 elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
582 }
584 if (elemIsCached) {
585 Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
586 }
588 retElem = SharedRegion_getPtr(elem->prev);
590 if (retElem == (ListMP_Elem *)(&(obj->attrs->head))) {
591 retElem = NULL;
592 }
594 if (elemIsCached) {
595 /* Invalidate because elem pulled into cache && elem != head. */
596 Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
597 }
599 return (retElem);
600 }
602 /*
603 * ======== ListMP_putHead ========
604 */
605 Int ListMP_putHead(ListMP_Handle handle, ListMP_Elem *elem)
606 {
607 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
608 UInt key;
609 UInt16 id;
610 ListMP_Elem *localNextElem;
611 SharedRegion_SRPtr sharedElem;
612 SharedRegion_SRPtr sharedHead;
613 Bool localNextElemIsCached;
615 /* prevent another thread or processor from modifying the ListMP */
616 key = GateMP_enter((GateMP_Handle)obj->gate);
618 id = SharedRegion_getId(elem);
619 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
620 sharedElem = (SharedRegion_SRPtr)elem;
621 sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head);
622 localNextElem = (ListMP_Elem *)obj->attrs->head.next;
623 }
624 else {
625 sharedElem = SharedRegion_getSRPtr(elem, id);
626 sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId);
627 localNextElem = SharedRegion_getPtr(obj->attrs->head.next);
628 }
630 /* Assert that pointer is not NULL */
631 Assert_isTrue(localNextElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
633 localNextElemIsCached = SharedRegion_isCacheEnabled(
634 SharedRegion_getId(localNextElem));
635 if (localNextElemIsCached) {
636 Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
637 }
639 /* add the new elem into the list */
640 elem->next = obj->attrs->head.next;
641 elem->prev = sharedHead;
642 localNextElem->prev = sharedElem;
643 obj->attrs->head.next = sharedElem;
645 if (localNextElemIsCached) {
646 /* Write-back because localNextElem->prev changed */
647 Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
648 }
649 if (obj->cacheEnabled) {
650 /* Write-back because obj->attrs->head.next changed */
651 Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL,
652 TRUE);
653 }
654 if (SharedRegion_isCacheEnabled(id)) {
655 /* Write-back because elem->next & elem->prev changed */
656 Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
657 }
659 GateMP_leave((GateMP_Handle)obj->gate, key);
661 return (ListMP_S_SUCCESS);
662 }
664 /*
665 * ======== ListMP_putTail ========
666 */
667 Int ListMP_putTail(ListMP_Handle handle, ListMP_Elem *elem)
668 {
669 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
670 UInt key;
671 UInt16 id;
672 ListMP_Elem *localPrevElem;
673 SharedRegion_SRPtr sharedElem;
674 SharedRegion_SRPtr sharedHead;
675 Bool localPrevElemIsCached;
677 /* prevent another thread or processor from modifying the ListMP */
678 key = GateMP_enter((GateMP_Handle)obj->gate);
680 id = SharedRegion_getId(elem);
681 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
682 sharedElem = (SharedRegion_SRPtr)elem;
683 sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head);
684 localPrevElem = (ListMP_Elem *)obj->attrs->head.prev;
685 }
686 else {
687 sharedElem = SharedRegion_getSRPtr(elem, id);
688 sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId);
689 localPrevElem = SharedRegion_getPtr(obj->attrs->head.prev);
690 }
692 /* Assert that pointer is not NULL */
693 Assert_isTrue(localPrevElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
695 localPrevElemIsCached = SharedRegion_isCacheEnabled(
696 SharedRegion_getId(localPrevElem));
697 if (localPrevElemIsCached) {
698 Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
699 }
701 /* add the new elem into the list */
702 elem->next = sharedHead;
703 elem->prev = obj->attrs->head.prev;
704 localPrevElem->next = sharedElem;
705 obj->attrs->head.prev = sharedElem;
707 if (localPrevElemIsCached) {
708 /* Write-back because localPrevElem->next changed */
709 Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
710 }
711 if (obj->cacheEnabled) {
712 /* Write-back because obj->attrs->head.prev changed */
713 Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL,
714 TRUE);
715 }
716 if (SharedRegion_isCacheEnabled(id)) {
717 /* Write-back because elem->next & elem->prev changed */
718 Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
719 }
721 GateMP_leave((GateMP_Handle)obj->gate, key);
723 return (ListMP_S_SUCCESS);
724 }
726 /*
727 * ======== ListMP_remove ========
728 */
729 Int ListMP_remove(ListMP_Handle handle, ListMP_Elem *elem)
730 {
731 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
732 UInt key;
733 ListMP_Elem *localPrevElem;
734 ListMP_Elem *localNextElem;
735 Bool localPrevElemIsCached, localNextElemIsCached;
737 /* Prevent another thread or processor from modifying the ListMP */
738 key = GateMP_enter((GateMP_Handle)obj->gate);
740 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
741 localPrevElem = (ListMP_Elem *)(elem->prev);
742 localNextElem = (ListMP_Elem *)(elem->next);
743 }
744 else {
745 localPrevElem = SharedRegion_getPtr(elem->prev);
746 localNextElem = SharedRegion_getPtr(elem->next);
747 }
749 localPrevElemIsCached = SharedRegion_isCacheEnabled(
750 SharedRegion_getId(localPrevElem));
751 localNextElemIsCached = SharedRegion_isCacheEnabled(
752 SharedRegion_getId(localNextElem));
754 if (localPrevElemIsCached) {
755 Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
756 }
757 if (localNextElemIsCached) {
758 Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
759 }
761 localPrevElem->next = elem->next;
762 localNextElem->prev = elem->prev;
764 if (localPrevElemIsCached) {
765 Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
766 }
767 if (localNextElemIsCached) {
768 Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
769 }
771 GateMP_leave((GateMP_Handle)obj->gate, key);
773 return (ListMP_S_SUCCESS);
774 }
776 /*
777 *************************************************************************
778 * Instance functions
779 *************************************************************************
780 */
782 /*
783 * ======== ti_sdo_ipc_ListMP_Instance_init ========
784 */
785 Int ti_sdo_ipc_ListMP_Instance_init(ti_sdo_ipc_ListMP_Object *obj,
786 const ti_sdo_ipc_ListMP_Params *params,
787 Error_Block *eb)
788 {
789 SharedRegion_SRPtr sharedShmBase;
790 Ptr localAddr;
791 Int status;
792 ListMP_Params sparams;
793 IHeap_Handle regionHeap;
795 if (params->openFlag == TRUE) {
796 /* Open by sharedAddr */
797 obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC;
798 obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
799 obj->regionId = SharedRegion_getId(&(obj->attrs->head));
800 obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
801 obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
803 /* get the local address of the SRPtr */
804 localAddr = SharedRegion_getPtr(obj->attrs->gateMPAddr);
806 status = GateMP_openByAddr(localAddr, (GateMP_Handle *)&(obj->gate));
807 if (status != GateMP_S_SUCCESS) {
808 Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
809 return (1);
810 }
812 return (0);
813 }
815 /* init the gate */
816 if (params->gate != NULL) {
817 obj->gate = params->gate;
818 }
819 else {
820 obj->gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
821 }
823 if (params->sharedAddr == NULL) {
824 /* Creating using a shared region ID */
825 obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION;
826 obj->regionId = params->regionId;
827 obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
828 obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
830 /* Need to allocate from the heap */
831 ListMP_Params_init(&sparams);
832 sparams.regionId = params->regionId;
833 obj->allocSize = ListMP_sharedMemReq(&sparams);
835 regionHeap = SharedRegion_getHeap(obj->regionId);
836 Assert_isTrue(regionHeap != NULL, ti_sdo_ipc_SharedRegion_A_noHeap);
838 /* The region heap will take care of the alignment */
839 obj->attrs = Memory_alloc(regionHeap, obj->allocSize, 0, eb);
841 if (obj->attrs == NULL) {
842 return (2);
843 }
844 }
845 else {
846 /* Creating using sharedAddr */
847 obj->regionId = SharedRegion_getId(params->sharedAddr);
849 /* Assert that the buffer is in a valid shared region */
850 Assert_isTrue(obj->regionId != SharedRegion_INVALIDREGIONID,
851 ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
853 /* set object's cacheEnabled, objType, and attrs */
854 obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
855 obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
856 obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC;
857 obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
859 /* Assert that sharedAddr is cache aligned */
860 Assert_isTrue((obj->cacheLineSize == 0) ||
861 ((UInt32)params->sharedAddr % obj->cacheLineSize == 0),
862 ti_sdo_ipc_Ipc_A_addrNotCacheAligned);
863 }
865 /* init the head (to be empty) */
866 ListMP_elemClear(&(obj->attrs->head));
868 /* store the GateMP sharedAddr in the Attrs */
869 obj->attrs->gateMPAddr = ti_sdo_ipc_GateMP_getSharedAddr(obj->gate);
871 /* last thing, set the status */
872 obj->attrs->status = ti_sdo_ipc_ListMP_CREATED;
874 if (obj->cacheEnabled) {
875 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
876 Cache_Type_ALL, TRUE);
877 }
879 /* add to NameServer if name not NULL */
880 if (params->name != NULL) {
881 sharedShmBase = SharedRegion_getSRPtr(obj->attrs, obj->regionId);
882 obj->nsKey = NameServer_addUInt32(
883 (NameServer_Handle)ListMP_module->nameServer, params->name,
884 (UInt32)sharedShmBase);
886 if (obj->nsKey == NULL) {
887 Error_raise(eb, ti_sdo_ipc_Ipc_E_nameFailed, params->name, 0);
888 return (3);
889 }
890 }
892 return (0);
893 }
895 /*
896 * ======== ti_sdo_ipc_ListMP_Instance_finalize ========
897 */
898 Void ti_sdo_ipc_ListMP_Instance_finalize(ti_sdo_ipc_ListMP_Object *obj,
899 Int status)
900 {
901 if (obj->objType & (ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC |
902 ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION)) {
903 /* List is being deleted */
904 /* Remove entry from NameServer */
905 if (obj->nsKey != NULL) {
906 NameServer_removeEntry((NameServer_Handle)ListMP_module->nameServer,
907 obj->nsKey);
908 }
910 /* Set status to 'not created' */
911 if (obj->attrs != NULL) {
912 obj->attrs->status = 0;
913 if (obj->cacheEnabled == TRUE) {
914 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
915 Cache_Type_ALL, TRUE);
916 }
917 }
919 /*
920 * Free the shared memory back to the region heap. If NULL, then the
921 * Memory_alloc failed.
922 */
923 if (obj->objType == ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION &&
924 obj->attrs != NULL) {
925 Memory_free(SharedRegion_getHeap(obj->regionId), obj->attrs,
926 obj->allocSize);
927 }
928 }
929 else {
930 /* List is being closed */
931 /* Close the gate. If NULL, then GateMP_openByAddr failed. */
932 if (obj->gate != NULL) {
933 GateMP_close((GateMP_Handle *)&(obj->gate));
934 }
935 }
936 }
938 /*
939 *************************************************************************
940 * Module functions
941 *************************************************************************
942 */
943 /*
944 * ======== ti_sdo_ipc_ListMP_elemClear ========
945 */
946 Void ti_sdo_ipc_ListMP_elemClear(ti_sdo_ipc_ListMP_Elem *elem)
947 {
948 SharedRegion_SRPtr sharedElem;
949 UInt16 id;
951 id = SharedRegion_getId(elem);
952 sharedElem = SharedRegion_getSRPtr(elem, id);
954 elem->next = elem->prev = sharedElem;
955 if (SharedRegion_isCacheEnabled(id)) {
956 Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
957 }
958 }