659757b52bfe28aa1deb279f561480f813e24857
[ipc/ipcdev.git] / packages / ti / sdo / ipc / ListMP.c
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)
101     /* init the params to the defaults */
102     params->gate       = NULL;
103     params->sharedAddr = 0;
104     params->name       = NULL;
105     params->regionId   = 0;
108 /*
109  *  ======== ListMP_create ========
110  */
111 ListMP_Handle ListMP_create(const ListMP_Params *params)
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);
138 /*
139  *  ======== ListMP_close ========
140  */
141 Int ListMP_close(ListMP_Handle *handlePtr)
143     ListMP_delete(handlePtr);
145     return (ListMP_S_SUCCESS);
148 /*
149  *  ======== ListMP_delete ========
150  */
151 Int ListMP_delete(ListMP_Handle *handlePtr)
153     ti_sdo_ipc_ListMP_delete((ti_sdo_ipc_ListMP_Handle *)handlePtr);
155     return (ListMP_S_SUCCESS);
158 /*
159  *  ======== ListMP_open ========
160  */
161 Int ListMP_open(String name, ListMP_Handle *handlePtr)
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);
194 /*
195  *  ======== ListMP_openByAddr ========
196  */
197 Int ListMP_openByAddr(Ptr sharedAddr, ListMP_Handle *handlePtr)
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(&params);
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(&params, &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);
242 /*
243  *  ======== ListMP_sharedMemReq ========
244  */
245 SizeT ListMP_sharedMemReq(const ListMP_Params *params)
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);
271 /*
272  *  ======== ListMP_empty ========
273  */
274 Bool ListMP_empty(ListMP_Handle handle)
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 #ifdef xdc_target__isaCompatible_v7A
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);
317 /*
318  *  ======== ListMP_getGate ========
319  */
320 GateMP_Handle ListMP_getGate(ListMP_Handle handle)
322     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
324     return ((GateMP_Handle)obj->gate);
327 /*
328  *  ======== ListMP_getHead ========
329  */
330 Ptr ListMP_getHead(ListMP_Handle handle)
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 #ifdef xdc_target__isaCompatible_v7A
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);
410 /*
411  *  ======== ListMP_getTail ========
412  */
413 Ptr ListMP_getTail(ListMP_Handle handle)
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 #ifdef xdc_target__isaCompatible_v7A
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);
493 /*
494  *  ======== ListMP_insert ========
495  */
496 Int ListMP_insert(ListMP_Handle handle, ListMP_Elem *newElem,
497                   ListMP_Elem *curElem)
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);
568 /*
569  *  ======== ListMP_next ========
570  */
571 Ptr ListMP_next(ListMP_Handle handle, ListMP_Elem *elem)
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);
605 /*
606  *  ======== ListMP_prev ========
607  */
608 Ptr ListMP_prev(ListMP_Handle handle, ListMP_Elem *elem)
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);
641 /*
642  *  ======== ListMP_putHead ========
643  */
644 Int ListMP_putHead(ListMP_Handle handle, ListMP_Elem *elem)
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 #ifdef xdc_target__isaCompatible_v7A
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);
712 /*
713  *  ======== ListMP_putTail ========
714  */
715 Int ListMP_putTail(ListMP_Handle handle, ListMP_Elem *elem)
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 #ifdef xdc_target__isaCompatible_v7A
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);
783 /*
784  *  ======== ListMP_remove ========
785  */
786 Int ListMP_remove(ListMP_Handle handle, ListMP_Elem *elem)
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);
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)
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 #ifdef xdc_target__isaCompatible_v7A
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);
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)
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     }
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)
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     }