SDOCM00116544 Cache management for ARM speculative execution
[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  */
83 /*
84  *  ======== ListMP_Params_init ========
85  */
86 Void ListMP_Params_init(ListMP_Params *params)
87 {
88     /* init the params to the defaults */
89     params->gate       = NULL;
90     params->sharedAddr = 0;
91     params->name       = NULL;
92     params->regionId   = 0;
93 }
95 /*
96  *  ======== ListMP_create ========
97  */
98 ListMP_Handle ListMP_create(const ListMP_Params *params)
99 {
100     ti_sdo_ipc_ListMP_Params mpParams;
101     ti_sdo_ipc_ListMP_Object *obj;
102     Error_Block eb;
104     Error_init(&eb);
106     if (params != NULL) {
107         /* init the module params struct */
108         ti_sdo_ipc_ListMP_Params_init(&mpParams);
109         mpParams.gate       = (ti_sdo_ipc_GateMP_Handle)params->gate;
110         mpParams.openFlag   = FALSE;
111         mpParams.sharedAddr = params->sharedAddr;
112         mpParams.name       = params->name;
113         mpParams.regionId   = params->regionId;
115         /* call the module create */
116         obj = ti_sdo_ipc_ListMP_create(&mpParams, &eb);
117     }
118     else {
119         obj = ti_sdo_ipc_ListMP_create(NULL, &eb);
120     }
122     return ((ListMP_Handle)obj);
125 /*
126  *  ======== ListMP_close ========
127  */
128 Int ListMP_close(ListMP_Handle *handlePtr)
130     ListMP_delete(handlePtr);
132     return (ListMP_S_SUCCESS);
135 /*
136  *  ======== ListMP_delete ========
137  */
138 Int ListMP_delete(ListMP_Handle *handlePtr)
140     ti_sdo_ipc_ListMP_delete((ti_sdo_ipc_ListMP_Handle *)handlePtr);
142     return (ListMP_S_SUCCESS);
145 /*
146  *  ======== ListMP_open ========
147  */
148 Int ListMP_open(String name, ListMP_Handle *handlePtr)
150     SharedRegion_SRPtr sharedShmBase;
151     Ptr sharedAddr;
152     Int status;
154     /* Assert that a pointer has been supplied */
155     Assert_isTrue(handlePtr != NULL, ti_sdo_ipc_Ipc_A_nullArgument);
157     /* Assert that we have enough information to open the gate */
158     Assert_isTrue(name != NULL, ti_sdo_ipc_Ipc_A_invParam);
160     /* Search NameServer */
161     status = NameServer_getUInt32((NameServer_Handle)ListMP_module->nameServer,
162             name, &sharedShmBase, MultiProc_getClusterProcList());
164     if (status < 0) {
165         /* Name was not found */
166         *handlePtr = NULL;
167         return (ListMP_E_NOTFOUND);
168     }
170     sharedAddr = SharedRegion_getPtr(sharedShmBase);
172     status = ListMP_openByAddr(sharedAddr, handlePtr);
174     return (status);
177 /*
178  *  ======== ListMP_openByAddr ========
179  */
180 Int ListMP_openByAddr(Ptr sharedAddr, ListMP_Handle *handlePtr)
182     ti_sdo_ipc_ListMP_Params params;
183     ti_sdo_ipc_ListMP_Attrs *attrs;
184     Error_Block eb;
185     Int status;
186     UInt16 id;
188     Error_init(&eb);
190     ti_sdo_ipc_ListMP_Params_init(&params);
192     /* Tell Instance_init() that we're opening */
193     params.openFlag = TRUE;
195     attrs = (ti_sdo_ipc_ListMP_Attrs *)sharedAddr;
196     params.sharedAddr = sharedAddr;
197     id = SharedRegion_getId(sharedAddr);
199     if (SharedRegion_isCacheEnabled(id)) {
200         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
201     }
203     if (attrs->status != ti_sdo_ipc_ListMP_CREATED) {
204         *handlePtr = NULL;
205         status = ListMP_E_NOTFOUND;
206     }
207     else {
208         /* Create the object */
209         *handlePtr = (ListMP_Handle)ti_sdo_ipc_ListMP_create(&params, &eb);
210         if (*handlePtr == NULL) {
211             status = ListMP_E_FAIL;
212         }
213         else {
214             status = ListMP_S_SUCCESS;
215         }
216     }
218     if (SharedRegion_isCacheEnabled(id)) {
219         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
220     }
222     return (status);
225 /*
226  *  ======== ListMP_sharedMemReq ========
227  */
228 SizeT ListMP_sharedMemReq(const ListMP_Params *params)
230     SizeT  memReq, minAlign;
231     UInt16 regionId;
233     if (params->sharedAddr == NULL) {
234         regionId = params->regionId;
235     }
236     else {
237         regionId = SharedRegion_getId(params->sharedAddr);
238     }
240     /* Assert that the region is valid */
241     Assert_isTrue(regionId != SharedRegion_INVALIDREGIONID,
242                   ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
244     minAlign = Memory_getMaxDefaultTypeAlign();
245     if (SharedRegion_getCacheLineSize(regionId) > minAlign) {
246         minAlign = SharedRegion_getCacheLineSize(regionId);
247     }
249     memReq = _Ipc_roundup(sizeof(ti_sdo_ipc_ListMP_Attrs), minAlign);
251     return (memReq);
254 /*
255  *  ======== ListMP_empty ========
256  */
257 Bool ListMP_empty(ListMP_Handle handle)
259     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
260     ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
261     Bool flag = FALSE;
262     IArg key;
263     SharedRegion_SRPtr sharedHead;
265     /* prevent another thread or processor from modifying the ListMP */
266     key = GateMP_enter((GateMP_Handle)obj->gate);
268 #ifdef xdc_target__isaCompatible_v7A
269     /* ARM speculative execution might have pulled attrs into cache */
270     if (obj->cacheEnabled) {
271         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
272     }
273 #endif
275     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
276         /* get the SRPtr for the head */
277         sharedHead = (SharedRegion_SRPtr)&(attrs->head);
278     }
279     else {
280         /* get the SRPtr for the head */
281         sharedHead = SharedRegion_getSRPtr(&(attrs->head), obj->regionId);
282     }
284     /* if 'next' is ourself, then the ListMP must be empty */
285     if (attrs->head.next == sharedHead) {
286         flag = TRUE;
287     }
289     if (obj->cacheEnabled) {
290         /* invalidate the head to make sure we are not getting stale data */
291         Cache_inv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
292     }
294     /* leave the gate */
295     GateMP_leave((GateMP_Handle)obj->gate, key);
297     return (flag);
300 /*
301  *  ======== ListMP_getGate ========
302  */
303 GateMP_Handle ListMP_getGate(ListMP_Handle handle)
305     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
307     return ((GateMP_Handle)obj->gate);
310 /*
311  *  ======== ListMP_getHead ========
312  */
313 Ptr ListMP_getHead(ListMP_Handle handle)
315     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
316     ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
317     ListMP_Elem *elem;
318     ListMP_Elem *localHeadNext;
319     ListMP_Elem *localNext;
320     Bool localNextIsCached;
321     UInt key;
323     /* prevent another thread or processor from modifying the ListMP */
324     key = GateMP_enter((GateMP_Handle)obj->gate);
326 #ifdef xdc_target__isaCompatible_v7A
327     /* ARM speculative execution might have pulled attrs into cache */
328     if (obj->cacheEnabled) {
329         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
330     }
331 #endif
333     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
334         localHeadNext = (ListMP_Elem *)attrs->head.next;
335     }
336     else {
337         localHeadNext = SharedRegion_getPtr(attrs->head.next);
338     }
340     /* Assert that pointer is not NULL */
341     Assert_isTrue(localHeadNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
343     /* See if the ListMP was empty */
344     if (localHeadNext == (ListMP_Elem *)(&(attrs->head))) {
345         /* Empty, return NULL */
346         elem = NULL;
347     }
348     else {
349         if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadNext))) {
350             /* invalidate elem */
351             Cache_inv(localHeadNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
352         }
354         if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
355             localNext = (ListMP_Elem *)localHeadNext->next;
356         }
357         else {
358             localNext = SharedRegion_getPtr(localHeadNext->next);
359         }
361         /* Assert that pointer is not NULL */
362         Assert_isTrue(localNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
364         /* Elem to return */
365         elem = localHeadNext;
366         localNextIsCached = SharedRegion_isCacheEnabled(
367                 SharedRegion_getId(localNext));
368         if (localNextIsCached) {
369             Cache_inv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
370         }
372         /* Fix the head of the list next pointer */
373         attrs->head.next = elem->next;
375         /* Fix the prev pointer of the new first elem on the list */
376         localNext->prev = localHeadNext->prev;
377         if (localNextIsCached) {
378             Cache_wbInv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
379         }
380     }
382     if (obj->cacheEnabled) {
383         Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
384     }
386     GateMP_leave((GateMP_Handle)obj->gate, key);
388     return (elem);
391 /*
392  *  ======== ListMP_getTail ========
393  */
394 Ptr ListMP_getTail(ListMP_Handle handle)
396     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
397     ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
398     ListMP_Elem *elem;
399     ListMP_Elem *localHeadPrev;
400     ListMP_Elem *localPrev;
401     Bool localPrevIsCached;
402     UInt key;
404     /* prevent another thread or processor from modifying the ListMP */
405     key = GateMP_enter((GateMP_Handle)obj->gate);
407 #ifdef xdc_target__isaCompatible_v7A
408     /* ARM speculative execution might have pulled attrs into cache */
409     if (obj->cacheEnabled) {
410         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
411     }
412 #endif
414     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
415         localHeadPrev = (ListMP_Elem *)attrs->head.prev;
416     }
417     else {
418         localHeadPrev = SharedRegion_getPtr(attrs->head.prev);
419     }
421     /* Assert that pointer is not NULL */
422     Assert_isTrue(localHeadPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
424     /* See if the ListMP was empty */
425     if (localHeadPrev == (ListMP_Elem *)(&(attrs->head))) {
426         /* Empty, return NULL */
427         elem = NULL;
428     }
429     else {
430         if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadPrev))) {
431             /* invalidate elem */
432             Cache_inv(localHeadPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
433         }
435         if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
436             localPrev = (ListMP_Elem *)localHeadPrev->prev;
437         }
438         else {
439             localPrev = SharedRegion_getPtr(localHeadPrev->prev);
440         }
442         /* Assert that pointer is not NULL */
443         Assert_isTrue(localPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
445         /* Elem to return */
446         elem = localHeadPrev;
447         localPrevIsCached = SharedRegion_isCacheEnabled(
448                 SharedRegion_getId(localPrev));
449         if (localPrevIsCached) {
450             Cache_inv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
451         }
453         /* Fix the head of the list prev pointer */
454         attrs->head.prev = elem->prev;
456         /* Fix the next pointer of the new last elem on the list */
457         localPrev->next = localHeadPrev->next;
458         if (localPrevIsCached) {
459             Cache_wbInv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
460         }
461     }
463     if (obj->cacheEnabled) {
464         Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
465     }
467     GateMP_leave((GateMP_Handle)obj->gate, key);
469     return (elem);
472 /*
473  *  ======== ListMP_insert ========
474  */
475 Int ListMP_insert(ListMP_Handle handle, ListMP_Elem *newElem,
476                   ListMP_Elem *curElem)
478     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
479     UInt key;
480     Int  id;
481     ListMP_Elem *localPrevElem;
482     SharedRegion_SRPtr sharedNewElem;
483     SharedRegion_SRPtr sharedCurElem;
484     Bool curElemIsCached, localPrevElemIsCached;
486     /* prevent another thread or processor from modifying the ListMP */
487     key = GateMP_enter((GateMP_Handle)obj->gate);
489     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
490         sharedNewElem = (SharedRegion_SRPtr)newElem;
491         sharedCurElem = (SharedRegion_SRPtr)curElem;
492     }
493     else {
494         /* get SRPtr for newElem */
495         id = SharedRegion_getId(newElem);
496         sharedNewElem = SharedRegion_getSRPtr(newElem, id);
498         /* get SRPtr for curElem */
499         id = SharedRegion_getId(curElem);
500         sharedCurElem = SharedRegion_getSRPtr(curElem, id);
501     }
503     curElemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(curElem));
504     if (curElemIsCached) {
505         Cache_inv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
506     }
508     /* get Ptr for curElem->prev */
509     localPrevElem = SharedRegion_getPtr(curElem->prev);
511     localPrevElemIsCached = SharedRegion_isCacheEnabled(
512             SharedRegion_getId(localPrevElem));
513     if (localPrevElemIsCached) {
514         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
515     }
517     newElem->next       = sharedCurElem;
518     newElem->prev       = curElem->prev;
519     localPrevElem->next = sharedNewElem;
520     curElem->prev       = sharedNewElem;
522     if (localPrevElemIsCached) {
523         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
524     }
526     /*
527      *  The next two Cache_wbInv needs to be done because curElem
528      *  and newElem are passed in and maybe already in the cache
529      */
530     if (curElemIsCached) {
531         /* writeback invalidate current elem structure */
532         Cache_wbInv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
533     }
535     if (SharedRegion_isCacheEnabled(SharedRegion_getId(newElem))) {
536         /* writeback invalidate new elem structure  */
537         Cache_wbInv(newElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
538     }
540     GateMP_leave((GateMP_Handle)obj->gate, key);
542     return (ListMP_S_SUCCESS);
545 /*
546  *  ======== ListMP_next ========
547  */
548 Ptr ListMP_next(ListMP_Handle handle, ListMP_Elem *elem)
550     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
551     ListMP_Elem *retElem;  /* returned elem */
552     Bool elemIsCached;
554     /* elem == NULL -> start at the head */
555     if (elem == NULL) {
556         /* Keep track of whether an extra Cache_inv is needed */
557         elemIsCached = obj->cacheEnabled;
558         elem = (ListMP_Elem *)&(obj->attrs->head);
559     }
560     else {
561         elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
562     }
564     if (elemIsCached) {
565         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
566     }
568     retElem = SharedRegion_getPtr(elem->next);
570     if (retElem == (ListMP_Elem *)(&obj->attrs->head)) {
571         retElem = NULL;
572     }
574     if (elemIsCached) {
575         /* invalidate because elem pulled into cache */
576         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
577     }
579     return (retElem);
582 /*
583  *  ======== ListMP_prev ========
584  */
585 Ptr ListMP_prev(ListMP_Handle handle, ListMP_Elem *elem)
587     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
588     ListMP_Elem *retElem;  /* returned elem */
589     Bool elemIsCached;
591     /* elem == NULL -> start at the head */
592     if (elem == NULL) {
593         elemIsCached = obj->cacheEnabled;
594         elem = (ListMP_Elem *)&(obj->attrs->head);
595     }
596     else {
597         elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
598     }
600     if (elemIsCached) {
601         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
602     }
604     retElem = SharedRegion_getPtr(elem->prev);
606     if (retElem == (ListMP_Elem *)(&(obj->attrs->head))) {
607         retElem = NULL;
608     }
610     if (elemIsCached) {
611         /* invalidate because elem pulled into cache */
612         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
613     }
615     return (retElem);
618 /*
619  *  ======== ListMP_putHead ========
620  */
621 Int ListMP_putHead(ListMP_Handle handle, ListMP_Elem *elem)
623     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
624     ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
625     UInt key;
626     UInt16 id;
627     ListMP_Elem *localNextElem;
628     SharedRegion_SRPtr sharedElem;
629     SharedRegion_SRPtr sharedHead;
630     Bool localNextElemIsCached;
632     /* prevent another thread or processor from modifying the ListMP */
633     key = GateMP_enter((GateMP_Handle)obj->gate);
635 #ifdef xdc_target__isaCompatible_v7A
636     /* ARM speculative execution might have pulled attrs into cache */
637     if (obj->cacheEnabled) {
638         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
639     }
640 #endif
642     id = SharedRegion_getId(elem);
643     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
644         sharedElem = (SharedRegion_SRPtr)elem;
645         sharedHead = (SharedRegion_SRPtr)&(attrs->head);
646         localNextElem = (ListMP_Elem *)attrs->head.next;
647     }
648     else {
649         sharedElem = SharedRegion_getSRPtr(elem, id);
650         sharedHead = SharedRegion_getSRPtr(&(attrs->head), obj->regionId);
651         localNextElem = SharedRegion_getPtr(attrs->head.next);
652     }
654     /* Assert that pointer is not NULL */
655     Assert_isTrue(localNextElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
657     localNextElemIsCached = SharedRegion_isCacheEnabled(
658         SharedRegion_getId(localNextElem));
659     if (localNextElemIsCached) {
660         Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
661     }
663     /* add the new elem into the list */
664     elem->next = attrs->head.next;
665     elem->prev = sharedHead;
666     localNextElem->prev = sharedElem;
667     attrs->head.next = sharedElem;
669     if (localNextElemIsCached) {
670         /* Write-back because localNextElem->prev changed */
671         Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
672     }
673     if (obj->cacheEnabled) {
674         /* Write-back because attrs->head.next changed */
675         Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
676     }
677     if (SharedRegion_isCacheEnabled(id)) {
678         /* Write-back because elem->next & elem->prev changed */
679         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
680     }
682     GateMP_leave((GateMP_Handle)obj->gate, key);
684     return (ListMP_S_SUCCESS);
687 /*
688  *  ======== ListMP_putTail ========
689  */
690 Int ListMP_putTail(ListMP_Handle handle, ListMP_Elem *elem)
692     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
693     ti_sdo_ipc_ListMP_Attrs *attrs = obj->attrs;
694     UInt key;
695     UInt16  id;
696     ListMP_Elem *localPrevElem;
697     SharedRegion_SRPtr sharedElem;
698     SharedRegion_SRPtr sharedHead;
699     Bool localPrevElemIsCached;
701     /* prevent another thread or processor from modifying the ListMP */
702     key = GateMP_enter((GateMP_Handle)obj->gate);
704 #ifdef xdc_target__isaCompatible_v7A
705     /* ARM speculative execution might have pulled attrs into cache */
706     if (obj->cacheEnabled) {
707         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
708     }
709 #endif
711     id = SharedRegion_getId(elem);
712     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
713         sharedElem = (SharedRegion_SRPtr)elem;
714         sharedHead = (SharedRegion_SRPtr)&(attrs->head);
715         localPrevElem = (ListMP_Elem *)attrs->head.prev;
716     }
717     else {
718         sharedElem = SharedRegion_getSRPtr(elem, id);
719         sharedHead = SharedRegion_getSRPtr(&(attrs->head), obj->regionId);
720         localPrevElem = SharedRegion_getPtr(attrs->head.prev);
721     }
723     /* Assert that pointer is not NULL */
724     Assert_isTrue(localPrevElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
726     localPrevElemIsCached = SharedRegion_isCacheEnabled(
727         SharedRegion_getId(localPrevElem));
728     if (localPrevElemIsCached) {
729         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
730     }
732     /* add the new elem into the list */
733     elem->next = sharedHead;
734     elem->prev = attrs->head.prev;
735     localPrevElem->next = sharedElem;
736     attrs->head.prev = sharedElem;
738     if (localPrevElemIsCached) {
739         /* Write-back because localPrevElem->next changed */
740         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
741     }
742     if (obj->cacheEnabled) {
743         /* Write-back because attrs->head.prev changed */
744         Cache_wbInv(&(attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
745     }
746     if (SharedRegion_isCacheEnabled(id)) {
747         /* Write-back because elem->next & elem->prev changed */
748         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
749     }
751     GateMP_leave((GateMP_Handle)obj->gate, key);
753     return (ListMP_S_SUCCESS);
756 /*
757  *  ======== ListMP_remove ========
758  */
759 Int ListMP_remove(ListMP_Handle handle, ListMP_Elem *elem)
761     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
762     UInt key;
763     ListMP_Elem *localPrevElem;
764     ListMP_Elem *localNextElem;
765     Bool localPrevElemIsCached, localNextElemIsCached;
767     /* Prevent another thread or processor from modifying the ListMP */
768     key = GateMP_enter((GateMP_Handle)obj->gate);
770     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
771         localPrevElem = (ListMP_Elem *)(elem->prev);
772         localNextElem = (ListMP_Elem *)(elem->next);
773     }
774     else {
775         localPrevElem = SharedRegion_getPtr(elem->prev);
776         localNextElem = SharedRegion_getPtr(elem->next);
777     }
779     localPrevElemIsCached = SharedRegion_isCacheEnabled(
780             SharedRegion_getId(localPrevElem));
781     localNextElemIsCached = SharedRegion_isCacheEnabled(
782             SharedRegion_getId(localNextElem));
784     if (localPrevElemIsCached) {
785         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
786     }
787     if (localNextElemIsCached) {
788         Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
789     }
791     localPrevElem->next = elem->next;
792     localNextElem->prev = elem->prev;
794     if (localPrevElemIsCached) {
795         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
796     }
797     if (localNextElemIsCached) {
798         Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
799     }
801     GateMP_leave((GateMP_Handle)obj->gate, key);
803     return (ListMP_S_SUCCESS);
806 /*
807  *************************************************************************
808  *                       Instance functions
809  *************************************************************************
810  */
812 /*
813  *  ======== ti_sdo_ipc_ListMP_Instance_init ========
814  */
815 Int ti_sdo_ipc_ListMP_Instance_init(ti_sdo_ipc_ListMP_Object *obj,
816         const ti_sdo_ipc_ListMP_Params *params,
817         Error_Block *eb)
819     SharedRegion_SRPtr sharedShmBase;
820     Ptr localAddr;
821     Int status;
822     ListMP_Params sparams;
823     IHeap_Handle regionHeap;
825     if (params->openFlag == TRUE) {
826         /* Open by sharedAddr */
827         obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC;
828         obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
829         obj->regionId = SharedRegion_getId(&(obj->attrs->head));
830         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
831         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
833 #ifdef xdc_target__isaCompatible_v7A
834     /* ARM speculative execution might have pulled attrs into cache */
835     if (obj->cacheEnabled) {
836         Cache_inv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL,
837                 TRUE);
838     }
839 #endif
840         /* get the local address of the SRPtr */
841         localAddr = SharedRegion_getPtr(obj->attrs->gateMPAddr);
843         status = GateMP_openByAddr(localAddr, (GateMP_Handle *)&(obj->gate));
844         if (status != GateMP_S_SUCCESS) {
845             Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
846             return (1);
847         }
849         return (0);
850     }
852     /* init the gate */
853     if (params->gate != NULL) {
854         obj->gate = params->gate;
855     }
856     else {
857         obj->gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
858     }
860     if (params->sharedAddr == NULL) {
861         /* Creating using a shared region ID */
862         obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION;
863         obj->regionId = params->regionId;
864         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
865         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
867         /* Need to allocate from the heap */
868         ListMP_Params_init(&sparams);
869         sparams.regionId = params->regionId;
870         obj->allocSize = ListMP_sharedMemReq(&sparams);
872         regionHeap = SharedRegion_getHeap(obj->regionId);
873         Assert_isTrue(regionHeap != NULL, ti_sdo_ipc_SharedRegion_A_noHeap);
875         /* The region heap will take care of the alignment */
876         obj->attrs = Memory_alloc(regionHeap, obj->allocSize, 0, eb);
878         if (obj->attrs == NULL) {
879             return (2);
880         }
881     }
882     else {
883         /* Creating using sharedAddr */
884         obj->regionId = SharedRegion_getId(params->sharedAddr);
886         /* Assert that the buffer is in a valid shared region */
887         Assert_isTrue(obj->regionId != SharedRegion_INVALIDREGIONID,
888                       ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
890         /* set object's cacheEnabled, objType, and attrs  */
891         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
892         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
893         obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC;
894         obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
896         /* Assert that sharedAddr is cache aligned */
897         Assert_isTrue((obj->cacheLineSize == 0) ||
898                       ((UInt32)params->sharedAddr % obj->cacheLineSize == 0),
899                       ti_sdo_ipc_Ipc_A_addrNotCacheAligned);
900     }
902     /* init the head (to be empty) */
903     ListMP_elemClear(&(obj->attrs->head));
905     /* store the GateMP sharedAddr in the Attrs */
906     obj->attrs->gateMPAddr = ti_sdo_ipc_GateMP_getSharedAddr(obj->gate);
908     /* last thing, set the status */
909     obj->attrs->status = ti_sdo_ipc_ListMP_CREATED;
911     if (obj->cacheEnabled) {
912         Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
913                 Cache_Type_ALL, TRUE);
914     }
916     /* add to NameServer if name not NULL */
917     if (params->name != NULL) {
918         sharedShmBase = SharedRegion_getSRPtr(obj->attrs, obj->regionId);
919         obj->nsKey = NameServer_addUInt32(
920             (NameServer_Handle)ListMP_module->nameServer, params->name,
921             (UInt32)sharedShmBase);
923         if (obj->nsKey == NULL) {
924             Error_raise(eb, ti_sdo_ipc_Ipc_E_nameFailed, params->name, 0);
925             return (3);
926         }
927     }
929     return (0);
932 /*
933  *  ======== ti_sdo_ipc_ListMP_Instance_finalize ========
934  */
935 Void ti_sdo_ipc_ListMP_Instance_finalize(ti_sdo_ipc_ListMP_Object *obj,
936         Int status)
938     if (obj->objType & (ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC |
939                         ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION)) {
940         /* List is being deleted */
941         /* Remove entry from NameServer */
942         if (obj->nsKey != NULL) {
943             NameServer_removeEntry((NameServer_Handle)ListMP_module->nameServer,
944                     obj->nsKey);
945         }
947         /* Set status to 'not created' */
948         if (obj->attrs != NULL) {
949             obj->attrs->status = 0;
950             if (obj->cacheEnabled == TRUE) {
951                 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
952                     Cache_Type_ALL, TRUE);
953             }
954         }
956         /*
957          *  Free the shared memory back to the region heap. If NULL, then the
958          *  Memory_alloc failed.
959          */
960         if (obj->objType == ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION &&
961             obj->attrs != NULL) {
962             Memory_free(SharedRegion_getHeap(obj->regionId), obj->attrs,
963                         obj->allocSize);
964         }
965     }
966     else {
967         /* List is being closed */
968         /* Close the gate. If NULL, then GateMP_openByAddr failed. */
969         if (obj->gate != NULL) {
970             GateMP_close((GateMP_Handle *)&(obj->gate));
971         }
972     }
975 /*
976  *************************************************************************
977  *                       Module functions
978  *************************************************************************
979  */
980 /*
981  *  ======== ti_sdo_ipc_ListMP_elemClear ========
982  */
983 Void ti_sdo_ipc_ListMP_elemClear(ti_sdo_ipc_ListMP_Elem *elem)
985     SharedRegion_SRPtr sharedElem;
986     UInt16 id;
988     id = SharedRegion_getId(elem);
989     sharedElem = SharedRegion_getSRPtr(elem, id);
991     elem->next = elem->prev = sharedElem;
992     if (SharedRegion_isCacheEnabled(id)) {
993         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
994     }