2f2bdb1886f8decd0ed6fbb7192518246ec6cae7
1 /*
2 * Copyright (c) 2012-2018 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 * ======== 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 */
82 /*
83 * ======== ListMP_barrier ========
84 * Function ensures all the writeback to memory is complete
85 */
86 static inline void ListMP_barrier(void)
87 {
88 #if defined(xdc_target__isaCompatible_64P)
89 /* Use _mfence to make sure memory transactions are complete */
90 _mfence();
91 /* Second mfence needed due to errata: See C6670 Advisory 32 */
92 _mfence();
93 #endif
94 }
96 /*
97 * ======== ListMP_Params_init ========
98 */
99 Void ListMP_Params_init(ListMP_Params *params)
100 {
101 /* init the params to the defaults */
102 params->gate = NULL;
103 params->sharedAddr = 0;
104 params->name = NULL;
105 params->regionId = 0;
106 }
108 /*
109 * ======== ListMP_create ========
110 */
111 ListMP_Handle ListMP_create(const ListMP_Params *params)
112 {
113 ti_sdo_ipc_ListMP_Params mpParams;
114 ti_sdo_ipc_ListMP_Object *obj;
115 Error_Block eb;
117 Error_init(&eb);
119 if (params != NULL) {
120 /* init the module params struct */
121 ti_sdo_ipc_ListMP_Params_init(&mpParams);
122 mpParams.gate = (ti_sdo_ipc_GateMP_Handle)params->gate;
123 mpParams.openFlag = FALSE;
124 mpParams.sharedAddr = params->sharedAddr;
125 mpParams.name = params->name;
126 mpParams.regionId = params->regionId;
128 /* call the module create */
129 obj = ti_sdo_ipc_ListMP_create(&mpParams, &eb);
130 }
131 else {
132 obj = ti_sdo_ipc_ListMP_create(NULL, &eb);
133 }
135 return ((ListMP_Handle)obj);
136 }
138 /*
139 * ======== ListMP_close ========
140 */
141 Int ListMP_close(ListMP_Handle *handlePtr)
142 {
143 ListMP_delete(handlePtr);
145 return (ListMP_S_SUCCESS);
146 }
148 /*
149 * ======== ListMP_delete ========
150 */
151 Int ListMP_delete(ListMP_Handle *handlePtr)
152 {
153 ti_sdo_ipc_ListMP_delete((ti_sdo_ipc_ListMP_Handle *)handlePtr);
155 return (ListMP_S_SUCCESS);
156 }
158 /*
159 * ======== ListMP_open ========
160 */
161 Int ListMP_open(String name, ListMP_Handle *handlePtr)
162 {
163 SharedRegion_SRPtr sharedShmBase;
164 Ptr sharedAddr;
165 Int status;
167 /* Assert that a pointer has been supplied */
168 Assert_isTrue(handlePtr != NULL, ti_sdo_ipc_Ipc_A_nullArgument);
170 /* Assert that we have enough information to open the gate */
171 Assert_isTrue(name != NULL, ti_sdo_ipc_Ipc_A_invParam);
173 /* Search NameServer */
174 status = NameServer_getUInt32((NameServer_Handle)ListMP_module->nameServer,
175 name, &sharedShmBase, MultiProc_getClusterProcList());
177 if (status < 0) {
178 /* Name was not found */
179 *handlePtr = NULL;
180 return (ListMP_E_NOTFOUND);
181 }
183 sharedAddr = SharedRegion_getPtr(sharedShmBase);
184 if ( sharedAddr == NULL ) {
185 *handlePtr = NULL;
186 return (ListMP_E_NOTFOUND);
187 }
189 status = ListMP_openByAddr(sharedAddr, handlePtr);
191 return (status);
192 }
194 /*
195 * ======== ListMP_openByAddr ========
196 */
197 Int ListMP_openByAddr(Ptr sharedAddr, ListMP_Handle *handlePtr)
198 {
199 ti_sdo_ipc_ListMP_Params params;
200 ti_sdo_ipc_ListMP_Attrs *attrs;
201 Error_Block eb;
202 Int status;
203 UInt16 id;
205 Error_init(&eb);
207 ti_sdo_ipc_ListMP_Params_init(¶ms);
209 /* Tell Instance_init() that we're opening */
210 params.openFlag = TRUE;
212 attrs = (ti_sdo_ipc_ListMP_Attrs *)sharedAddr;
213 params.sharedAddr = sharedAddr;
214 id = SharedRegion_getId(sharedAddr);
216 if (SharedRegion_isCacheEnabled(id)) {
217 Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
218 }
220 if (attrs->status != ti_sdo_ipc_ListMP_CREATED) {
221 *handlePtr = NULL;
222 status = ListMP_E_NOTFOUND;
223 }
224 else {
225 /* Create the object */
226 *handlePtr = (ListMP_Handle)ti_sdo_ipc_ListMP_create(¶ms, &eb);
227 if (*handlePtr == NULL) {
228 status = ListMP_E_FAIL;
229 }
230 else {
231 status = ListMP_S_SUCCESS;
232 }
233 }
235 if (SharedRegion_isCacheEnabled(id)) {
236 Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
237 }
239 return (status);
240 }
242 /*
243 * ======== ListMP_sharedMemReq ========
244 */
245 SizeT ListMP_sharedMemReq(const ListMP_Params *params)
246 {
247 SizeT memReq, minAlign;
248 UInt16 regionId;
250 if (params->sharedAddr == NULL) {
251 regionId = params->regionId;
252 }
253 else {
254 regionId = SharedRegion_getId(params->sharedAddr);
255 }
257 /* Assert that the region is valid */
258 Assert_isTrue(regionId != SharedRegion_INVALIDREGIONID,
259 ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
261 minAlign = Memory_getMaxDefaultTypeAlign();
262 if (SharedRegion_getCacheLineSize(regionId) > minAlign) {
263 minAlign = SharedRegion_getCacheLineSize(regionId);
264 }
266 memReq = _Ipc_roundup(sizeof(ti_sdo_ipc_ListMP_Attrs), minAlign);
268 return (memReq);
269 }
271 /*
272 * ======== ListMP_empty ========
273 */
274 Bool ListMP_empty(ListMP_Handle handle)
275 {
276 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
277 ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
278 Bool flag = FALSE;
279 IArg key;
280 SharedRegion_SRPtr sharedHead;
282 /* prevent another thread or processor from modifying the ListMP */
283 key = GateMP_enter((GateMP_Handle)obj->gate);
285 #if defined(xdc_target__isaCompatible_v7A) || defined(xdc_target__isaCompatible_v8A)
286 /* ARM speculative execution might have pulled attrs into cache */
287 if (obj->cacheEnabled) {
288 Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
289 }
290 #endif
292 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
293 /* get the SRPtr for the head */
294 sharedHead = (SharedRegion_SRPtr)&(attrs->head);
295 }
296 else {
297 /* get the SRPtr for the head */
298 sharedHead = SharedRegion_getSRPtr(&(attrs->head), obj->regionId);
299 }
301 /* if 'next' is ourself, then the ListMP must be empty */
302 if (attrs->head.next == sharedHead) {
303 flag = TRUE;
304 }
306 if (obj->cacheEnabled) {
307 /* invalidate the head to make sure we are not getting stale data */
308 Cache_inv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
309 }
311 /* leave the gate */
312 GateMP_leave((GateMP_Handle)obj->gate, key);
314 return (flag);
315 }
317 /*
318 * ======== ListMP_getGate ========
319 */
320 GateMP_Handle ListMP_getGate(ListMP_Handle handle)
321 {
322 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
324 return ((GateMP_Handle)obj->gate);
325 }
327 /*
328 * ======== ListMP_getHead ========
329 */
330 Ptr ListMP_getHead(ListMP_Handle handle)
331 {
332 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
333 ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
334 ListMP_Elem *elem;
335 ListMP_Elem *localHeadNext;
336 ListMP_Elem *localNext;
337 Bool localNextIsCached;
338 UInt key;
340 /* prevent another thread or processor from modifying the ListMP */
341 key = GateMP_enter((GateMP_Handle)obj->gate);
343 #if defined(xdc_target__isaCompatible_v7A) || defined(xdc_target__isaCompatible_v8A)
344 /* ARM speculative execution might have pulled attrs into cache */
345 if (obj->cacheEnabled) {
346 Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
347 }
348 #endif
350 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
351 localHeadNext = (ListMP_Elem *)attrs->head.next;
352 }
353 else {
354 localHeadNext = SharedRegion_getPtr(attrs->head.next);
355 }
357 /* Assert that pointer is not NULL */
358 Assert_isTrue(localHeadNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
360 /* See if the ListMP was empty */
361 if (localHeadNext == (ListMP_Elem *)(&(attrs->head))) {
362 /* Empty, return NULL */
363 elem = NULL;
364 }
365 else {
366 if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadNext))) {
367 /* invalidate elem */
368 Cache_inv(localHeadNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
369 }
371 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
372 localNext = (ListMP_Elem *)localHeadNext->next;
373 }
374 else {
375 localNext = SharedRegion_getPtr(localHeadNext->next);
376 }
378 /* Assert that pointer is not NULL */
379 Assert_isTrue(localNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
381 /* Elem to return */
382 elem = localHeadNext;
383 localNextIsCached = SharedRegion_isCacheEnabled(
384 SharedRegion_getId(localNext));
385 if (localNextIsCached) {
386 Cache_inv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
387 }
389 /* Fix the head of the list next pointer */
390 attrs->head.next = elem->next;
392 /* Fix the prev pointer of the new first elem on the list */
393 localNext->prev = localHeadNext->prev;
394 if (localNextIsCached) {
395 Cache_wbInv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
396 }
397 }
399 if (obj->cacheEnabled) {
400 Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
401 }
402 else
403 ListMP_barrier();
405 GateMP_leave((GateMP_Handle)obj->gate, key);
407 return (elem);
408 }
410 /*
411 * ======== ListMP_getTail ========
412 */
413 Ptr ListMP_getTail(ListMP_Handle handle)
414 {
415 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
416 ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
417 ListMP_Elem *elem;
418 ListMP_Elem *localHeadPrev;
419 ListMP_Elem *localPrev;
420 Bool localPrevIsCached;
421 UInt key;
423 /* prevent another thread or processor from modifying the ListMP */
424 key = GateMP_enter((GateMP_Handle)obj->gate);
426 #if defined(xdc_target__isaCompatible_v7A) || defined(xdc_target__isaCompatible_v8A)
427 /* ARM speculative execution might have pulled attrs into cache */
428 if (obj->cacheEnabled) {
429 Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
430 }
431 #endif
433 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
434 localHeadPrev = (ListMP_Elem *)attrs->head.prev;
435 }
436 else {
437 localHeadPrev = SharedRegion_getPtr(attrs->head.prev);
438 }
440 /* Assert that pointer is not NULL */
441 Assert_isTrue(localHeadPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
443 /* See if the ListMP was empty */
444 if (localHeadPrev == (ListMP_Elem *)(&(attrs->head))) {
445 /* Empty, return NULL */
446 elem = NULL;
447 }
448 else {
449 if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadPrev))) {
450 /* invalidate elem */
451 Cache_inv(localHeadPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
452 }
454 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
455 localPrev = (ListMP_Elem *)localHeadPrev->prev;
456 }
457 else {
458 localPrev = SharedRegion_getPtr(localHeadPrev->prev);
459 }
461 /* Assert that pointer is not NULL */
462 Assert_isTrue(localPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
464 /* Elem to return */
465 elem = localHeadPrev;
466 localPrevIsCached = SharedRegion_isCacheEnabled(
467 SharedRegion_getId(localPrev));
468 if (localPrevIsCached) {
469 Cache_inv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
470 }
472 /* Fix the head of the list prev pointer */
473 attrs->head.prev = elem->prev;
475 /* Fix the next pointer of the new last elem on the list */
476 localPrev->next = localHeadPrev->next;
477 if (localPrevIsCached) {
478 Cache_wbInv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
479 }
480 }
482 if (obj->cacheEnabled) {
483 Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
484 }
485 else
486 ListMP_barrier();
488 GateMP_leave((GateMP_Handle)obj->gate, key);
490 return (elem);
491 }
493 /*
494 * ======== ListMP_insert ========
495 */
496 Int ListMP_insert(ListMP_Handle handle, ListMP_Elem *newElem,
497 ListMP_Elem *curElem)
498 {
499 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
500 UInt key;
501 Int id;
502 ListMP_Elem *localPrevElem;
503 SharedRegion_SRPtr sharedNewElem;
504 SharedRegion_SRPtr sharedCurElem;
505 Bool curElemIsCached, localPrevElemIsCached;
507 /* prevent another thread or processor from modifying the ListMP */
508 key = GateMP_enter((GateMP_Handle)obj->gate);
510 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
511 sharedNewElem = (SharedRegion_SRPtr)newElem;
512 sharedCurElem = (SharedRegion_SRPtr)curElem;
513 }
514 else {
515 /* get SRPtr for newElem */
516 id = SharedRegion_getId(newElem);
517 sharedNewElem = SharedRegion_getSRPtr(newElem, id);
519 /* get SRPtr for curElem */
520 id = SharedRegion_getId(curElem);
521 sharedCurElem = SharedRegion_getSRPtr(curElem, id);
522 }
524 curElemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(curElem));
525 if (curElemIsCached) {
526 Cache_inv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
527 }
529 /* get Ptr for curElem->prev */
530 localPrevElem = SharedRegion_getPtr(curElem->prev);
532 localPrevElemIsCached = SharedRegion_isCacheEnabled(
533 SharedRegion_getId(localPrevElem));
534 if (localPrevElemIsCached) {
535 Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
536 }
538 newElem->next = sharedCurElem;
539 newElem->prev = curElem->prev;
540 localPrevElem->next = sharedNewElem;
541 curElem->prev = sharedNewElem;
543 if (localPrevElemIsCached) {
544 Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
545 }
547 /*
548 * The next two Cache_wbInv needs to be done because curElem
549 * and newElem are passed in and maybe already in the cache
550 */
551 if (curElemIsCached) {
552 /* writeback invalidate current elem structure */
553 Cache_wbInv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
554 }
556 if (SharedRegion_isCacheEnabled(SharedRegion_getId(newElem))) {
557 /* writeback invalidate new elem structure */
558 Cache_wbInv(newElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
559 }
560 else
561 ListMP_barrier();
563 GateMP_leave((GateMP_Handle)obj->gate, key);
565 return (ListMP_S_SUCCESS);
566 }
568 /*
569 * ======== ListMP_next ========
570 */
571 Ptr ListMP_next(ListMP_Handle handle, ListMP_Elem *elem)
572 {
573 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
574 ListMP_Elem *retElem; /* returned elem */
575 Bool elemIsCached;
577 /* elem == NULL -> start at the head */
578 if (elem == NULL) {
579 /* Keep track of whether an extra Cache_inv is needed */
580 elemIsCached = obj->cacheEnabled;
581 elem = (ListMP_Elem *)&(obj->attrs->head);
582 }
583 else {
584 elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
585 }
587 if (elemIsCached) {
588 Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
589 }
591 retElem = SharedRegion_getPtr(elem->next);
593 if (retElem == (ListMP_Elem *)(&obj->attrs->head)) {
594 retElem = NULL;
595 }
597 if (elemIsCached) {
598 /* invalidate because elem pulled into cache */
599 Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
600 }
602 return (retElem);
603 }
605 /*
606 * ======== ListMP_prev ========
607 */
608 Ptr ListMP_prev(ListMP_Handle handle, ListMP_Elem *elem)
609 {
610 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
611 ListMP_Elem *retElem; /* returned elem */
612 Bool elemIsCached;
614 /* elem == NULL -> start at the head */
615 if (elem == NULL) {
616 elemIsCached = obj->cacheEnabled;
617 elem = (ListMP_Elem *)&(obj->attrs->head);
618 }
619 else {
620 elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
621 }
623 if (elemIsCached) {
624 Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
625 }
627 retElem = SharedRegion_getPtr(elem->prev);
629 if (retElem == (ListMP_Elem *)(&(obj->attrs->head))) {
630 retElem = NULL;
631 }
633 if (elemIsCached) {
634 /* invalidate because elem pulled into cache */
635 Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
636 }
638 return (retElem);
639 }
641 /*
642 * ======== ListMP_putHead ========
643 */
644 Int ListMP_putHead(ListMP_Handle handle, ListMP_Elem *elem)
645 {
646 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
647 ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
648 UInt key;
649 UInt16 id;
650 ListMP_Elem *localNextElem;
651 SharedRegion_SRPtr sharedElem;
652 SharedRegion_SRPtr sharedHead;
653 Bool localNextElemIsCached;
655 /* prevent another thread or processor from modifying the ListMP */
656 key = GateMP_enter((GateMP_Handle)obj->gate);
658 #if defined(xdc_target__isaCompatible_v7A) || defined(xdc_target__isaCompatible_v8A)
659 /* ARM speculative execution might have pulled attrs into cache */
660 if (obj->cacheEnabled) {
661 Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
662 }
663 #endif
665 id = SharedRegion_getId(elem);
666 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
667 sharedElem = (SharedRegion_SRPtr)elem;
668 sharedHead = (SharedRegion_SRPtr)&(attrs->head);
669 localNextElem = (ListMP_Elem *)attrs->head.next;
670 }
671 else {
672 sharedElem = SharedRegion_getSRPtr(elem, id);
673 sharedHead = SharedRegion_getSRPtr(&(attrs->head), obj->regionId);
674 localNextElem = SharedRegion_getPtr(attrs->head.next);
675 }
677 /* Assert that pointer is not NULL */
678 Assert_isTrue(localNextElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
680 localNextElemIsCached = SharedRegion_isCacheEnabled(
681 SharedRegion_getId(localNextElem));
682 if (localNextElemIsCached) {
683 Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
684 }
686 /* add the new elem into the list */
687 elem->next = attrs->head.next;
688 elem->prev = sharedHead;
689 localNextElem->prev = sharedElem;
690 attrs->head.next = sharedElem;
692 if (localNextElemIsCached) {
693 /* Write-back because localNextElem->prev changed */
694 Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
695 }
696 if (obj->cacheEnabled) {
697 /* Write-back because attrs->head.next changed */
698 Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
699 }
700 if (SharedRegion_isCacheEnabled(id)) {
701 /* Write-back because elem->next & elem->prev changed */
702 Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
703 }
704 else
705 ListMP_barrier();
707 GateMP_leave((GateMP_Handle)obj->gate, key);
709 return (ListMP_S_SUCCESS);
710 }
712 /*
713 * ======== ListMP_putTail ========
714 */
715 Int ListMP_putTail(ListMP_Handle handle, ListMP_Elem *elem)
716 {
717 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
718 ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
719 UInt key;
720 UInt16 id;
721 ListMP_Elem *localPrevElem;
722 SharedRegion_SRPtr sharedElem;
723 SharedRegion_SRPtr sharedHead;
724 Bool localPrevElemIsCached;
726 /* prevent another thread or processor from modifying the ListMP */
727 key = GateMP_enter((GateMP_Handle)obj->gate);
729 #if defined(xdc_target__isaCompatible_v7A) || defined(xdc_target__isaCompatible_v8A)
730 /* ARM speculative execution might have pulled attrs into cache */
731 if (obj->cacheEnabled) {
732 Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
733 }
734 #endif
736 id = SharedRegion_getId(elem);
737 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
738 sharedElem = (SharedRegion_SRPtr)elem;
739 sharedHead = (SharedRegion_SRPtr)&(attrs->head);
740 localPrevElem = (ListMP_Elem *)attrs->head.prev;
741 }
742 else {
743 sharedElem = SharedRegion_getSRPtr(elem, id);
744 sharedHead = SharedRegion_getSRPtr(&(attrs->head), obj->regionId);
745 localPrevElem = SharedRegion_getPtr(attrs->head.prev);
746 }
748 /* Assert that pointer is not NULL */
749 Assert_isTrue(localPrevElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
751 localPrevElemIsCached = SharedRegion_isCacheEnabled(
752 SharedRegion_getId(localPrevElem));
753 if (localPrevElemIsCached) {
754 Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
755 }
757 /* add the new elem into the list */
758 elem->next = sharedHead;
759 elem->prev = attrs->head.prev;
760 localPrevElem->next = sharedElem;
761 attrs->head.prev = sharedElem;
763 if (localPrevElemIsCached) {
764 /* Write-back because localPrevElem->next changed */
765 Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
766 }
767 if (obj->cacheEnabled) {
768 /* Write-back because attrs->head.prev changed */
769 Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
770 }
771 if (SharedRegion_isCacheEnabled(id)) {
772 /* Write-back because elem->next & elem->prev changed */
773 Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
774 }
775 else
776 ListMP_barrier();
778 GateMP_leave((GateMP_Handle)obj->gate, key);
780 return (ListMP_S_SUCCESS);
781 }
783 /*
784 * ======== ListMP_remove ========
785 */
786 Int ListMP_remove(ListMP_Handle handle, ListMP_Elem *elem)
787 {
788 ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
789 UInt key;
790 ListMP_Elem *localPrevElem;
791 ListMP_Elem *localNextElem;
792 Bool localPrevElemIsCached, localNextElemIsCached;
794 /* Prevent another thread or processor from modifying the ListMP */
795 key = GateMP_enter((GateMP_Handle)obj->gate);
797 if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
798 localPrevElem = (ListMP_Elem *)(elem->prev);
799 localNextElem = (ListMP_Elem *)(elem->next);
800 }
801 else {
802 localPrevElem = SharedRegion_getPtr(elem->prev);
803 localNextElem = SharedRegion_getPtr(elem->next);
804 }
806 localPrevElemIsCached = SharedRegion_isCacheEnabled(
807 SharedRegion_getId(localPrevElem));
808 localNextElemIsCached = SharedRegion_isCacheEnabled(
809 SharedRegion_getId(localNextElem));
811 if (localPrevElemIsCached) {
812 Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
813 }
814 if (localNextElemIsCached) {
815 Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
816 }
818 localPrevElem->next = elem->next;
819 localNextElem->prev = elem->prev;
821 if (localPrevElemIsCached) {
822 Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
823 }
824 if (localNextElemIsCached) {
825 Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
826 }
827 else
828 ListMP_barrier();
830 GateMP_leave((GateMP_Handle)obj->gate, key);
832 return (ListMP_S_SUCCESS);
833 }
835 /*
836 *************************************************************************
837 * Instance functions
838 *************************************************************************
839 */
841 /*
842 * ======== ti_sdo_ipc_ListMP_Instance_init ========
843 */
844 Int ti_sdo_ipc_ListMP_Instance_init(ti_sdo_ipc_ListMP_Object *obj,
845 const ti_sdo_ipc_ListMP_Params *params,
846 Error_Block *eb)
847 {
848 SharedRegion_SRPtr sharedShmBase;
849 Ptr localAddr;
850 Int status;
851 ListMP_Params sparams;
852 IHeap_Handle regionHeap;
854 if (params->openFlag == TRUE) {
855 /* Open by sharedAddr */
856 obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC;
857 obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
858 obj->regionId = SharedRegion_getId(&(obj->attrs->head));
859 obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
860 obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
862 #if defined(xdc_target__isaCompatible_v7A) || defined(xdc_target__isaCompatible_v8A)
863 /* ARM speculative execution might have pulled attrs into cache */
864 if (obj->cacheEnabled) {
865 Cache_inv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL,
866 TRUE);
867 }
868 #endif
869 /* get the local address of the SRPtr */
870 localAddr = SharedRegion_getPtr(obj->attrs->gateMPAddr);
872 /* Do NULL check on localAddr */
873 Assert_isTrue(localAddr != NULL, ti_sdo_ipc_Ipc_A_internal);
875 status = GateMP_openByAddr(localAddr, (GateMP_Handle *)&(obj->gate));
876 if (status != GateMP_S_SUCCESS) {
877 Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
878 return (1);
879 }
881 return (0);
882 }
884 /* init the gate */
885 if (params->gate != NULL) {
886 obj->gate = params->gate;
887 }
888 else {
889 obj->gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
890 }
892 if (params->sharedAddr == NULL) {
893 /* Creating using a shared region ID */
894 obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION;
895 obj->regionId = params->regionId;
896 obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
897 obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
899 /* Need to allocate from the heap */
900 ListMP_Params_init(&sparams);
901 sparams.regionId = params->regionId;
902 obj->allocSize = ListMP_sharedMemReq(&sparams);
904 regionHeap = SharedRegion_getHeap(obj->regionId);
905 Assert_isTrue(regionHeap != NULL, ti_sdo_ipc_SharedRegion_A_noHeap);
907 /* The region heap will take care of the alignment */
908 obj->attrs = Memory_alloc(regionHeap, obj->allocSize, 0, eb);
910 if (obj->attrs == NULL) {
911 return (2);
912 }
913 }
914 else {
915 /* Creating using sharedAddr */
916 obj->regionId = SharedRegion_getId(params->sharedAddr);
918 /* Assert that the buffer is in a valid shared region */
919 Assert_isTrue(obj->regionId != SharedRegion_INVALIDREGIONID,
920 ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
922 /* set object's cacheEnabled, objType, and attrs */
923 obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
924 obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
925 obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC;
926 obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
928 /* Assert that sharedAddr is cache aligned */
929 Assert_isTrue((obj->cacheLineSize == 0) ||
930 ((UInt32)params->sharedAddr % obj->cacheLineSize == 0),
931 ti_sdo_ipc_Ipc_A_addrNotCacheAligned);
932 }
934 /* init the head (to be empty) */
935 ListMP_elemClear(&(obj->attrs->head));
937 /* store the GateMP sharedAddr in the Attrs */
938 obj->attrs->gateMPAddr = ti_sdo_ipc_GateMP_getSharedAddr(obj->gate);
940 /* last thing, set the status */
941 obj->attrs->status = ti_sdo_ipc_ListMP_CREATED;
943 if (obj->cacheEnabled) {
944 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
945 Cache_Type_ALL, TRUE);
946 }
948 /* add to NameServer if name not NULL */
949 if (params->name != NULL) {
950 sharedShmBase = SharedRegion_getSRPtr(obj->attrs, obj->regionId);
951 obj->nsKey = NameServer_addUInt32(
952 (NameServer_Handle)ListMP_module->nameServer, params->name,
953 (UInt32)sharedShmBase);
955 if (obj->nsKey == NULL) {
956 Error_raise(eb, ti_sdo_ipc_Ipc_E_nameFailed, params->name, 0);
957 return (3);
958 }
959 }
961 return (0);
962 }
964 /*
965 * ======== ti_sdo_ipc_ListMP_Instance_finalize ========
966 */
967 Void ti_sdo_ipc_ListMP_Instance_finalize(ti_sdo_ipc_ListMP_Object *obj,
968 Int status)
969 {
970 if (obj->objType & (ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC |
971 ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION)) {
972 /* List is being deleted */
973 /* Remove entry from NameServer */
974 if (obj->nsKey != NULL) {
975 NameServer_removeEntry((NameServer_Handle)ListMP_module->nameServer,
976 obj->nsKey);
977 }
979 /* Set status to 'not created' */
980 if (obj->attrs != NULL) {
981 obj->attrs->status = 0;
982 if (obj->cacheEnabled == TRUE) {
983 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
984 Cache_Type_ALL, TRUE);
985 }
986 }
988 /*
989 * Free the shared memory back to the region heap. If NULL, then the
990 * Memory_alloc failed.
991 */
992 if (obj->objType == ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION &&
993 obj->attrs != NULL) {
994 Memory_free(SharedRegion_getHeap(obj->regionId), obj->attrs,
995 obj->allocSize);
996 }
997 }
998 else {
999 /* List is being closed */
1000 /* Close the gate. If NULL, then GateMP_openByAddr failed. */
1001 if (obj->gate != NULL) {
1002 GateMP_close((GateMP_Handle *)&(obj->gate));
1003 }
1004 }
1005 }
1007 /*
1008 *************************************************************************
1009 * Module functions
1010 *************************************************************************
1011 */
1012 /*
1013 * ======== ti_sdo_ipc_ListMP_elemClear ========
1014 */
1015 Void ti_sdo_ipc_ListMP_elemClear(ti_sdo_ipc_ListMP_Elem *elem)
1016 {
1017 SharedRegion_SRPtr sharedElem;
1018 UInt16 id;
1020 id = SharedRegion_getId(elem);
1021 sharedElem = SharedRegion_getSRPtr(elem, id);
1023 elem->next = elem->prev = sharedElem;
1024 if (SharedRegion_isCacheEnabled(id)) {
1025 Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
1026 }
1027 }