ListMP: Add barrier to ensure write backs complete
[ipc/ipcdev.git] / packages / ti / sdo / ipc / ListMP.c
1 /*
2  * Copyright (c) 2012-2015 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);
185     status = ListMP_openByAddr(sharedAddr, handlePtr);
187     return (status);
190 /*
191  *  ======== ListMP_openByAddr ========
192  */
193 Int ListMP_openByAddr(Ptr sharedAddr, ListMP_Handle *handlePtr)
195     ti_sdo_ipc_ListMP_Params params;
196     ti_sdo_ipc_ListMP_Attrs *attrs;
197     Error_Block eb;
198     Int status;
199     UInt16 id;
201     Error_init(&eb);
203     ti_sdo_ipc_ListMP_Params_init(&params);
205     /* Tell Instance_init() that we're opening */
206     params.openFlag = TRUE;
208     attrs = (ti_sdo_ipc_ListMP_Attrs *)sharedAddr;
209     params.sharedAddr = sharedAddr;
210     id = SharedRegion_getId(sharedAddr);
212     if (SharedRegion_isCacheEnabled(id)) {
213         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
214     }
216     if (attrs->status != ti_sdo_ipc_ListMP_CREATED) {
217         *handlePtr = NULL;
218         status = ListMP_E_NOTFOUND;
219     }
220     else {
221         /* Create the object */
222         *handlePtr = (ListMP_Handle)ti_sdo_ipc_ListMP_create(&params, &eb);
223         if (*handlePtr == NULL) {
224             status = ListMP_E_FAIL;
225         }
226         else {
227             status = ListMP_S_SUCCESS;
228         }
229     }
231     if (SharedRegion_isCacheEnabled(id)) {
232         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
233     }
235     return (status);
238 /*
239  *  ======== ListMP_sharedMemReq ========
240  */
241 SizeT ListMP_sharedMemReq(const ListMP_Params *params)
243     SizeT  memReq, minAlign;
244     UInt16 regionId;
246     if (params->sharedAddr == NULL) {
247         regionId = params->regionId;
248     }
249     else {
250         regionId = SharedRegion_getId(params->sharedAddr);
251     }
253     /* Assert that the region is valid */
254     Assert_isTrue(regionId != SharedRegion_INVALIDREGIONID,
255                   ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
257     minAlign = Memory_getMaxDefaultTypeAlign();
258     if (SharedRegion_getCacheLineSize(regionId) > minAlign) {
259         minAlign = SharedRegion_getCacheLineSize(regionId);
260     }
262     memReq = _Ipc_roundup(sizeof(ti_sdo_ipc_ListMP_Attrs), minAlign);
264     return (memReq);
267 /*
268  *  ======== ListMP_empty ========
269  */
270 Bool ListMP_empty(ListMP_Handle handle)
272     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
273     ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
274     Bool flag = FALSE;
275     IArg key;
276     SharedRegion_SRPtr sharedHead;
278     /* prevent another thread or processor from modifying the ListMP */
279     key = GateMP_enter((GateMP_Handle)obj->gate);
281 #ifdef xdc_target__isaCompatible_v7A
282     /* ARM speculative execution might have pulled attrs into cache */
283     if (obj->cacheEnabled) {
284         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
285     }
286 #endif
288     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
289         /* get the SRPtr for the head */
290         sharedHead = (SharedRegion_SRPtr)&(attrs->head);
291     }
292     else {
293         /* get the SRPtr for the head */
294         sharedHead = SharedRegion_getSRPtr(&(attrs->head), obj->regionId);
295     }
297     /* if 'next' is ourself, then the ListMP must be empty */
298     if (attrs->head.next == sharedHead) {
299         flag = TRUE;
300     }
302     if (obj->cacheEnabled) {
303         /* invalidate the head to make sure we are not getting stale data */
304         Cache_inv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
305     }
307     /* leave the gate */
308     GateMP_leave((GateMP_Handle)obj->gate, key);
310     return (flag);
313 /*
314  *  ======== ListMP_getGate ========
315  */
316 GateMP_Handle ListMP_getGate(ListMP_Handle handle)
318     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
320     return ((GateMP_Handle)obj->gate);
323 /*
324  *  ======== ListMP_getHead ========
325  */
326 Ptr ListMP_getHead(ListMP_Handle handle)
328     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
329     ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
330     ListMP_Elem *elem;
331     ListMP_Elem *localHeadNext;
332     ListMP_Elem *localNext;
333     Bool localNextIsCached;
334     UInt key;
336     /* prevent another thread or processor from modifying the ListMP */
337     key = GateMP_enter((GateMP_Handle)obj->gate);
339 #ifdef xdc_target__isaCompatible_v7A
340     /* ARM speculative execution might have pulled attrs into cache */
341     if (obj->cacheEnabled) {
342         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
343     }
344 #endif
346     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
347         localHeadNext = (ListMP_Elem *)attrs->head.next;
348     }
349     else {
350         localHeadNext = SharedRegion_getPtr(attrs->head.next);
351     }
353     /* Assert that pointer is not NULL */
354     Assert_isTrue(localHeadNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
356     /* See if the ListMP was empty */
357     if (localHeadNext == (ListMP_Elem *)(&(attrs->head))) {
358         /* Empty, return NULL */
359         elem = NULL;
360     }
361     else {
362         if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadNext))) {
363             /* invalidate elem */
364             Cache_inv(localHeadNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
365         }
367         if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
368             localNext = (ListMP_Elem *)localHeadNext->next;
369         }
370         else {
371             localNext = SharedRegion_getPtr(localHeadNext->next);
372         }
374         /* Assert that pointer is not NULL */
375         Assert_isTrue(localNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
377         /* Elem to return */
378         elem = localHeadNext;
379         localNextIsCached = SharedRegion_isCacheEnabled(
380                 SharedRegion_getId(localNext));
381         if (localNextIsCached) {
382             Cache_inv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
383         }
385         /* Fix the head of the list next pointer */
386         attrs->head.next = elem->next;
388         /* Fix the prev pointer of the new first elem on the list */
389         localNext->prev = localHeadNext->prev;
390         if (localNextIsCached) {
391             Cache_wbInv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
392         }
393     }
395     if (obj->cacheEnabled) {
396         Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
397     }
398     else
399         ListMP_barrier();
401     GateMP_leave((GateMP_Handle)obj->gate, key);
403     return (elem);
406 /*
407  *  ======== ListMP_getTail ========
408  */
409 Ptr ListMP_getTail(ListMP_Handle handle)
411     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
412     ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
413     ListMP_Elem *elem;
414     ListMP_Elem *localHeadPrev;
415     ListMP_Elem *localPrev;
416     Bool localPrevIsCached;
417     UInt key;
419     /* prevent another thread or processor from modifying the ListMP */
420     key = GateMP_enter((GateMP_Handle)obj->gate);
422 #ifdef xdc_target__isaCompatible_v7A
423     /* ARM speculative execution might have pulled attrs into cache */
424     if (obj->cacheEnabled) {
425         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
426     }
427 #endif
429     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
430         localHeadPrev = (ListMP_Elem *)attrs->head.prev;
431     }
432     else {
433         localHeadPrev = SharedRegion_getPtr(attrs->head.prev);
434     }
436     /* Assert that pointer is not NULL */
437     Assert_isTrue(localHeadPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
439     /* See if the ListMP was empty */
440     if (localHeadPrev == (ListMP_Elem *)(&(attrs->head))) {
441         /* Empty, return NULL */
442         elem = NULL;
443     }
444     else {
445         if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadPrev))) {
446             /* invalidate elem */
447             Cache_inv(localHeadPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
448         }
450         if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
451             localPrev = (ListMP_Elem *)localHeadPrev->prev;
452         }
453         else {
454             localPrev = SharedRegion_getPtr(localHeadPrev->prev);
455         }
457         /* Assert that pointer is not NULL */
458         Assert_isTrue(localPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
460         /* Elem to return */
461         elem = localHeadPrev;
462         localPrevIsCached = SharedRegion_isCacheEnabled(
463                 SharedRegion_getId(localPrev));
464         if (localPrevIsCached) {
465             Cache_inv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
466         }
468         /* Fix the head of the list prev pointer */
469         attrs->head.prev = elem->prev;
471         /* Fix the next pointer of the new last elem on the list */
472         localPrev->next = localHeadPrev->next;
473         if (localPrevIsCached) {
474             Cache_wbInv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
475         }
476     }
478     if (obj->cacheEnabled) {
479         Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
480     }
481     else
482         ListMP_barrier();
484     GateMP_leave((GateMP_Handle)obj->gate, key);
486     return (elem);
489 /*
490  *  ======== ListMP_insert ========
491  */
492 Int ListMP_insert(ListMP_Handle handle, ListMP_Elem *newElem,
493                   ListMP_Elem *curElem)
495     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
496     UInt key;
497     Int  id;
498     ListMP_Elem *localPrevElem;
499     SharedRegion_SRPtr sharedNewElem;
500     SharedRegion_SRPtr sharedCurElem;
501     Bool curElemIsCached, localPrevElemIsCached;
503     /* prevent another thread or processor from modifying the ListMP */
504     key = GateMP_enter((GateMP_Handle)obj->gate);
506     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
507         sharedNewElem = (SharedRegion_SRPtr)newElem;
508         sharedCurElem = (SharedRegion_SRPtr)curElem;
509     }
510     else {
511         /* get SRPtr for newElem */
512         id = SharedRegion_getId(newElem);
513         sharedNewElem = SharedRegion_getSRPtr(newElem, id);
515         /* get SRPtr for curElem */
516         id = SharedRegion_getId(curElem);
517         sharedCurElem = SharedRegion_getSRPtr(curElem, id);
518     }
520     curElemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(curElem));
521     if (curElemIsCached) {
522         Cache_inv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
523     }
525     /* get Ptr for curElem->prev */
526     localPrevElem = SharedRegion_getPtr(curElem->prev);
528     localPrevElemIsCached = SharedRegion_isCacheEnabled(
529             SharedRegion_getId(localPrevElem));
530     if (localPrevElemIsCached) {
531         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
532     }
534     newElem->next       = sharedCurElem;
535     newElem->prev       = curElem->prev;
536     localPrevElem->next = sharedNewElem;
537     curElem->prev       = sharedNewElem;
539     if (localPrevElemIsCached) {
540         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
541     }
543     /*
544      *  The next two Cache_wbInv needs to be done because curElem
545      *  and newElem are passed in and maybe already in the cache
546      */
547     if (curElemIsCached) {
548         /* writeback invalidate current elem structure */
549         Cache_wbInv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
550     }
552     if (SharedRegion_isCacheEnabled(SharedRegion_getId(newElem))) {
553         /* writeback invalidate new elem structure  */
554         Cache_wbInv(newElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
555     }
556     else
557         ListMP_barrier();
559     GateMP_leave((GateMP_Handle)obj->gate, key);
561     return (ListMP_S_SUCCESS);
564 /*
565  *  ======== ListMP_next ========
566  */
567 Ptr ListMP_next(ListMP_Handle handle, ListMP_Elem *elem)
569     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
570     ListMP_Elem *retElem;  /* returned elem */
571     Bool elemIsCached;
573     /* elem == NULL -> start at the head */
574     if (elem == NULL) {
575         /* Keep track of whether an extra Cache_inv is needed */
576         elemIsCached = obj->cacheEnabled;
577         elem = (ListMP_Elem *)&(obj->attrs->head);
578     }
579     else {
580         elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
581     }
583     if (elemIsCached) {
584         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
585     }
587     retElem = SharedRegion_getPtr(elem->next);
589     if (retElem == (ListMP_Elem *)(&obj->attrs->head)) {
590         retElem = NULL;
591     }
593     if (elemIsCached) {
594         /* invalidate because elem pulled into cache */
595         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
596     }
598     return (retElem);
601 /*
602  *  ======== ListMP_prev ========
603  */
604 Ptr ListMP_prev(ListMP_Handle handle, ListMP_Elem *elem)
606     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
607     ListMP_Elem *retElem;  /* returned elem */
608     Bool elemIsCached;
610     /* elem == NULL -> start at the head */
611     if (elem == NULL) {
612         elemIsCached = obj->cacheEnabled;
613         elem = (ListMP_Elem *)&(obj->attrs->head);
614     }
615     else {
616         elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
617     }
619     if (elemIsCached) {
620         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
621     }
623     retElem = SharedRegion_getPtr(elem->prev);
625     if (retElem == (ListMP_Elem *)(&(obj->attrs->head))) {
626         retElem = NULL;
627     }
629     if (elemIsCached) {
630         /* invalidate because elem pulled into cache */
631         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
632     }
634     return (retElem);
637 /*
638  *  ======== ListMP_putHead ========
639  */
640 Int ListMP_putHead(ListMP_Handle handle, ListMP_Elem *elem)
642     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
643     ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
644     UInt key;
645     UInt16 id;
646     ListMP_Elem *localNextElem;
647     SharedRegion_SRPtr sharedElem;
648     SharedRegion_SRPtr sharedHead;
649     Bool localNextElemIsCached;
651     /* prevent another thread or processor from modifying the ListMP */
652     key = GateMP_enter((GateMP_Handle)obj->gate);
654 #ifdef xdc_target__isaCompatible_v7A
655     /* ARM speculative execution might have pulled attrs into cache */
656     if (obj->cacheEnabled) {
657         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
658     }
659 #endif
661     id = SharedRegion_getId(elem);
662     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
663         sharedElem = (SharedRegion_SRPtr)elem;
664         sharedHead = (SharedRegion_SRPtr)&(attrs->head);
665         localNextElem = (ListMP_Elem *)attrs->head.next;
666     }
667     else {
668         sharedElem = SharedRegion_getSRPtr(elem, id);
669         sharedHead = SharedRegion_getSRPtr(&(attrs->head), obj->regionId);
670         localNextElem = SharedRegion_getPtr(attrs->head.next);
671     }
673     /* Assert that pointer is not NULL */
674     Assert_isTrue(localNextElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
676     localNextElemIsCached = SharedRegion_isCacheEnabled(
677         SharedRegion_getId(localNextElem));
678     if (localNextElemIsCached) {
679         Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
680     }
682     /* add the new elem into the list */
683     elem->next = attrs->head.next;
684     elem->prev = sharedHead;
685     localNextElem->prev = sharedElem;
686     attrs->head.next = sharedElem;
688     if (localNextElemIsCached) {
689         /* Write-back because localNextElem->prev changed */
690         Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
691     }
692     if (obj->cacheEnabled) {
693         /* Write-back because attrs->head.next changed */
694         Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
695     }
696     if (SharedRegion_isCacheEnabled(id)) {
697         /* Write-back because elem->next & elem->prev changed */
698         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
699     }
700     else
701         ListMP_barrier();
703     GateMP_leave((GateMP_Handle)obj->gate, key);
705     return (ListMP_S_SUCCESS);
708 /*
709  *  ======== ListMP_putTail ========
710  */
711 Int ListMP_putTail(ListMP_Handle handle, ListMP_Elem *elem)
713     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
714     ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
715     UInt key;
716     UInt16  id;
717     ListMP_Elem *localPrevElem;
718     SharedRegion_SRPtr sharedElem;
719     SharedRegion_SRPtr sharedHead;
720     Bool localPrevElemIsCached;
722     /* prevent another thread or processor from modifying the ListMP */
723     key = GateMP_enter((GateMP_Handle)obj->gate);
725 #ifdef xdc_target__isaCompatible_v7A
726     /* ARM speculative execution might have pulled attrs into cache */
727     if (obj->cacheEnabled) {
728         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
729     }
730 #endif
732     id = SharedRegion_getId(elem);
733     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
734         sharedElem = (SharedRegion_SRPtr)elem;
735         sharedHead = (SharedRegion_SRPtr)&(attrs->head);
736         localPrevElem = (ListMP_Elem *)attrs->head.prev;
737     }
738     else {
739         sharedElem = SharedRegion_getSRPtr(elem, id);
740         sharedHead = SharedRegion_getSRPtr(&(attrs->head), obj->regionId);
741         localPrevElem = SharedRegion_getPtr(attrs->head.prev);
742     }
744     /* Assert that pointer is not NULL */
745     Assert_isTrue(localPrevElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
747     localPrevElemIsCached = SharedRegion_isCacheEnabled(
748         SharedRegion_getId(localPrevElem));
749     if (localPrevElemIsCached) {
750         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
751     }
753     /* add the new elem into the list */
754     elem->next = sharedHead;
755     elem->prev = attrs->head.prev;
756     localPrevElem->next = sharedElem;
757     attrs->head.prev = sharedElem;
759     if (localPrevElemIsCached) {
760         /* Write-back because localPrevElem->next changed */
761         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
762     }
763     if (obj->cacheEnabled) {
764         /* Write-back because attrs->head.prev changed */
765         Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
766     }
767     if (SharedRegion_isCacheEnabled(id)) {
768         /* Write-back because elem->next & elem->prev changed */
769         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
770     }
771     else
772         ListMP_barrier();
774     GateMP_leave((GateMP_Handle)obj->gate, key);
776     return (ListMP_S_SUCCESS);
779 /*
780  *  ======== ListMP_remove ========
781  */
782 Int ListMP_remove(ListMP_Handle handle, ListMP_Elem *elem)
784     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
785     UInt key;
786     ListMP_Elem *localPrevElem;
787     ListMP_Elem *localNextElem;
788     Bool localPrevElemIsCached, localNextElemIsCached;
790     /* Prevent another thread or processor from modifying the ListMP */
791     key = GateMP_enter((GateMP_Handle)obj->gate);
793     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
794         localPrevElem = (ListMP_Elem *)(elem->prev);
795         localNextElem = (ListMP_Elem *)(elem->next);
796     }
797     else {
798         localPrevElem = SharedRegion_getPtr(elem->prev);
799         localNextElem = SharedRegion_getPtr(elem->next);
800     }
802     localPrevElemIsCached = SharedRegion_isCacheEnabled(
803             SharedRegion_getId(localPrevElem));
804     localNextElemIsCached = SharedRegion_isCacheEnabled(
805             SharedRegion_getId(localNextElem));
807     if (localPrevElemIsCached) {
808         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
809     }
810     if (localNextElemIsCached) {
811         Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
812     }
814     localPrevElem->next = elem->next;
815     localNextElem->prev = elem->prev;
817     if (localPrevElemIsCached) {
818         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
819     }
820     if (localNextElemIsCached) {
821         Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
822     }
823     else
824         ListMP_barrier();
826     GateMP_leave((GateMP_Handle)obj->gate, key);
828     return (ListMP_S_SUCCESS);
831 /*
832  *************************************************************************
833  *                       Instance functions
834  *************************************************************************
835  */
837 /*
838  *  ======== ti_sdo_ipc_ListMP_Instance_init ========
839  */
840 Int ti_sdo_ipc_ListMP_Instance_init(ti_sdo_ipc_ListMP_Object *obj,
841         const ti_sdo_ipc_ListMP_Params *params,
842         Error_Block *eb)
844     SharedRegion_SRPtr sharedShmBase;
845     Ptr localAddr;
846     Int status;
847     ListMP_Params sparams;
848     IHeap_Handle regionHeap;
850     if (params->openFlag == TRUE) {
851         /* Open by sharedAddr */
852         obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC;
853         obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
854         obj->regionId = SharedRegion_getId(&(obj->attrs->head));
855         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
856         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
858 #ifdef xdc_target__isaCompatible_v7A
859     /* ARM speculative execution might have pulled attrs into cache */
860     if (obj->cacheEnabled) {
861         Cache_inv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL,
862                 TRUE);
863     }
864 #endif
865         /* get the local address of the SRPtr */
866         localAddr = SharedRegion_getPtr(obj->attrs->gateMPAddr);
868         status = GateMP_openByAddr(localAddr, (GateMP_Handle *)&(obj->gate));
869         if (status != GateMP_S_SUCCESS) {
870             Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
871             return (1);
872         }
874         return (0);
875     }
877     /* init the gate */
878     if (params->gate != NULL) {
879         obj->gate = params->gate;
880     }
881     else {
882         obj->gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
883     }
885     if (params->sharedAddr == NULL) {
886         /* Creating using a shared region ID */
887         obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION;
888         obj->regionId = params->regionId;
889         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
890         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
892         /* Need to allocate from the heap */
893         ListMP_Params_init(&sparams);
894         sparams.regionId = params->regionId;
895         obj->allocSize = ListMP_sharedMemReq(&sparams);
897         regionHeap = SharedRegion_getHeap(obj->regionId);
898         Assert_isTrue(regionHeap != NULL, ti_sdo_ipc_SharedRegion_A_noHeap);
900         /* The region heap will take care of the alignment */
901         obj->attrs = Memory_alloc(regionHeap, obj->allocSize, 0, eb);
903         if (obj->attrs == NULL) {
904             return (2);
905         }
906     }
907     else {
908         /* Creating using sharedAddr */
909         obj->regionId = SharedRegion_getId(params->sharedAddr);
911         /* Assert that the buffer is in a valid shared region */
912         Assert_isTrue(obj->regionId != SharedRegion_INVALIDREGIONID,
913                       ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
915         /* set object's cacheEnabled, objType, and attrs  */
916         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
917         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
918         obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC;
919         obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
921         /* Assert that sharedAddr is cache aligned */
922         Assert_isTrue((obj->cacheLineSize == 0) ||
923                       ((UInt32)params->sharedAddr % obj->cacheLineSize == 0),
924                       ti_sdo_ipc_Ipc_A_addrNotCacheAligned);
925     }
927     /* init the head (to be empty) */
928     ListMP_elemClear(&(obj->attrs->head));
930     /* store the GateMP sharedAddr in the Attrs */
931     obj->attrs->gateMPAddr = ti_sdo_ipc_GateMP_getSharedAddr(obj->gate);
933     /* last thing, set the status */
934     obj->attrs->status = ti_sdo_ipc_ListMP_CREATED;
936     if (obj->cacheEnabled) {
937         Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
938                 Cache_Type_ALL, TRUE);
939     }
941     /* add to NameServer if name not NULL */
942     if (params->name != NULL) {
943         sharedShmBase = SharedRegion_getSRPtr(obj->attrs, obj->regionId);
944         obj->nsKey = NameServer_addUInt32(
945             (NameServer_Handle)ListMP_module->nameServer, params->name,
946             (UInt32)sharedShmBase);
948         if (obj->nsKey == NULL) {
949             Error_raise(eb, ti_sdo_ipc_Ipc_E_nameFailed, params->name, 0);
950             return (3);
951         }
952     }
954     return (0);
957 /*
958  *  ======== ti_sdo_ipc_ListMP_Instance_finalize ========
959  */
960 Void ti_sdo_ipc_ListMP_Instance_finalize(ti_sdo_ipc_ListMP_Object *obj,
961         Int status)
963     if (obj->objType & (ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC |
964                         ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION)) {
965         /* List is being deleted */
966         /* Remove entry from NameServer */
967         if (obj->nsKey != NULL) {
968             NameServer_removeEntry((NameServer_Handle)ListMP_module->nameServer,
969                     obj->nsKey);
970         }
972         /* Set status to 'not created' */
973         if (obj->attrs != NULL) {
974             obj->attrs->status = 0;
975             if (obj->cacheEnabled == TRUE) {
976                 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
977                     Cache_Type_ALL, TRUE);
978             }
979         }
981         /*
982          *  Free the shared memory back to the region heap. If NULL, then the
983          *  Memory_alloc failed.
984          */
985         if (obj->objType == ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION &&
986             obj->attrs != NULL) {
987             Memory_free(SharedRegion_getHeap(obj->regionId), obj->attrs,
988                         obj->allocSize);
989         }
990     }
991     else {
992         /* List is being closed */
993         /* Close the gate. If NULL, then GateMP_openByAddr failed. */
994         if (obj->gate != NULL) {
995             GateMP_close((GateMP_Handle *)&(obj->gate));
996         }
997     }
1000 /*
1001  *************************************************************************
1002  *                       Module functions
1003  *************************************************************************
1004  */
1005 /*
1006  *  ======== ti_sdo_ipc_ListMP_elemClear ========
1007  */
1008 Void ti_sdo_ipc_ListMP_elemClear(ti_sdo_ipc_ListMP_Elem *elem)
1010     SharedRegion_SRPtr sharedElem;
1011     UInt16 id;
1013     id = SharedRegion_getId(elem);
1014     sharedElem = SharedRegion_getSRPtr(elem, id);
1016     elem->next = elem->prev = sharedElem;
1017     if (SharedRegion_isCacheEnabled(id)) {
1018         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
1019     }