Merge branch '3.30' into ipc-next
[ipc/ipcdev.git] / packages / ti / sdo / ipc / ListMP.c
1 /*
2  * Copyright (c) 2012-2014 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     Bool flag = FALSE;
261     IArg key;
262     SharedRegion_SRPtr sharedHead;
264     /* prevent another thread or processor from modifying the ListMP */
265     key = GateMP_enter((GateMP_Handle)obj->gate);
268     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
269         /* get the SRPtr for the head */
270         sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head);
271     }
272     else {
273         /* get the SRPtr for the head */
274         sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId);
275     }
277     /* if 'next' is ourself, then the ListMP must be empty */
278     if (obj->attrs->head.next == sharedHead) {
279         flag = TRUE;
280     }
282     if (obj->cacheEnabled) {
283         /* invalidate the head to make sure we are not getting stale data */
284         Cache_inv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL,
285                   TRUE);
286     }
288     /* leave the gate */
289     GateMP_leave((GateMP_Handle)obj->gate, key);
291     return (flag);
294 /*
295  *  ======== ListMP_getGate ========
296  */
297 GateMP_Handle ListMP_getGate(ListMP_Handle handle)
299     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
301     return ((GateMP_Handle)obj->gate);
304 /*
305  *  ======== ListMP_getHead ========
306  */
307 Ptr ListMP_getHead(ListMP_Handle handle)
309     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
310     ListMP_Elem *elem;
311     ListMP_Elem *localHeadNext;
312     ListMP_Elem *localNext;
313     Bool localNextIsCached;
314     UInt key;
316     /* prevent another thread or processor from modifying the ListMP */
317     key = GateMP_enter((GateMP_Handle)obj->gate);
319     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
320         localHeadNext = (ListMP_Elem *)obj->attrs->head.next;
321     }
322     else {
323         localHeadNext = SharedRegion_getPtr(obj->attrs->head.next);
324     }
326     /* Assert that pointer is not NULL */
327     Assert_isTrue(localHeadNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
329     /* See if the ListMP was empty */
330     if (localHeadNext == (ListMP_Elem *)(&(obj->attrs->head))) {
331         /* Empty, return NULL */
332         elem = NULL;
333     }
334     else {
335         if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadNext))) {
336             /* invalidate elem */
337             Cache_inv(localHeadNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
338         }
340         if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
341             localNext = (ListMP_Elem *)localHeadNext->next;
342         }
343         else {
344             localNext = SharedRegion_getPtr(localHeadNext->next);
345         }
347         /* Assert that pointer is not NULL */
348         Assert_isTrue(localNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
350         /* Elem to return */
351         elem = localHeadNext;
352         localNextIsCached = SharedRegion_isCacheEnabled(
353                 SharedRegion_getId(localNext));
354         if (localNextIsCached) {
355             Cache_inv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
356         }
358         /* Fix the head of the list next pointer */
359         obj->attrs->head.next = elem->next;
361         /* Fix the prev pointer of the new first elem on the list */
362         localNext->prev = localHeadNext->prev;
363         if (localNextIsCached) {
364             Cache_wbInv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
365         }
366     }
368     if (obj->cacheEnabled) {
369         Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem),
370                     Cache_Type_ALL, TRUE);
371     }
373     GateMP_leave((GateMP_Handle)obj->gate, key);
375     return (elem);
378 /*
379  *  ======== ListMP_getTail ========
380  */
381 Ptr ListMP_getTail(ListMP_Handle handle)
383     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
384     ListMP_Elem *elem;
385     ListMP_Elem *localHeadPrev;
386     ListMP_Elem *localPrev;
387     Bool localPrevIsCached;
388     UInt key;
390     /* prevent another thread or processor from modifying the ListMP */
391     key = GateMP_enter((GateMP_Handle)obj->gate);
393     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
394         localHeadPrev = (ListMP_Elem *)obj->attrs->head.prev;
395     }
396     else {
397         localHeadPrev = SharedRegion_getPtr(obj->attrs->head.prev);
398     }
400     /* Assert that pointer is not NULL */
401     Assert_isTrue(localHeadPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
403     /* See if the ListMP was empty */
404     if (localHeadPrev == (ListMP_Elem *)(&(obj->attrs->head))) {
405         /* Empty, return NULL */
406         elem = NULL;
407     }
408     else {
409         if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadPrev))) {
410             /* invalidate elem */
411             Cache_inv(localHeadPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
412         }
414         if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
415             localPrev = (ListMP_Elem *)localHeadPrev->prev;
416         }
417         else {
418             localPrev = SharedRegion_getPtr(localHeadPrev->prev);
419         }
421         /* Assert that pointer is not NULL */
422         Assert_isTrue(localPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
424         /* Elem to return */
425         elem = localHeadPrev;
426         localPrevIsCached = SharedRegion_isCacheEnabled(
427                 SharedRegion_getId(localPrev));
428         if (localPrevIsCached) {
429             Cache_inv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
430         }
432         /* Fix the head of the list prev pointer */
433         obj->attrs->head.prev = elem->prev;
435         /* Fix the next pointer of the new last elem on the list */
436         localPrev->next = localHeadPrev->next;
437         if (localPrevIsCached) {
438             Cache_wbInv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
439         }
440     }
442     if (obj->cacheEnabled) {
443         Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem),
444                     Cache_Type_ALL, TRUE);
445     }
447     GateMP_leave((GateMP_Handle)obj->gate, key);
449     return (elem);
452 /*
453  *  ======== ListMP_insert ========
454  */
455 Int ListMP_insert(ListMP_Handle handle, ListMP_Elem *newElem,
456                   ListMP_Elem *curElem)
458     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
459     UInt key;
460     Int  id;
461     ListMP_Elem *localPrevElem;
462     SharedRegion_SRPtr sharedNewElem;
463     SharedRegion_SRPtr sharedCurElem;
464     Bool curElemIsCached, localPrevElemIsCached;
466     /* prevent another thread or processor from modifying the ListMP */
467     key = GateMP_enter((GateMP_Handle)obj->gate);
469     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
470         sharedNewElem = (SharedRegion_SRPtr)newElem;
471         sharedCurElem = (SharedRegion_SRPtr)curElem;
472         localPrevElem = (ListMP_Elem *)(curElem->prev);
473     }
474     else {
475         /* get SRPtr for newElem */
476         id = SharedRegion_getId(newElem);
477         sharedNewElem = SharedRegion_getSRPtr(newElem, id);
479         /* get SRPtr for curElem */
480         id = SharedRegion_getId(curElem);
481         sharedCurElem = SharedRegion_getSRPtr(curElem, id);
482     }
484     curElemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(curElem));
485     if (curElemIsCached) {
486         Cache_inv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
487     }
489     /* get Ptr for curElem->prev */
490     localPrevElem = SharedRegion_getPtr(curElem->prev);
492     localPrevElemIsCached = SharedRegion_isCacheEnabled(
493             SharedRegion_getId(localPrevElem));
494     if (localPrevElemIsCached) {
495         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
496     }
498     newElem->next       = sharedCurElem;
499     newElem->prev       = curElem->prev;
500     localPrevElem->next = sharedNewElem;
501     curElem->prev       = sharedNewElem;
503     if (localPrevElemIsCached) {
504         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
505     }
507     /*
508      *  The next two Cache_wbInv needs to be done because curElem
509      *  and newElem are passed in and maybe already in the cache
510      */
511     if (curElemIsCached) {
512         /* writeback invalidate current elem structure */
513         Cache_wbInv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
514     }
516     if (SharedRegion_isCacheEnabled(SharedRegion_getId(newElem))) {
517         /* writeback invalidate new elem structure  */
518         Cache_wbInv(newElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
519     }
521     GateMP_leave((GateMP_Handle)obj->gate, key);
523     return (ListMP_S_SUCCESS);
526 /*
527  *  ======== ListMP_next ========
528  */
529 Ptr ListMP_next(ListMP_Handle handle, ListMP_Elem *elem)
531     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
532     ListMP_Elem *retElem;  /* returned elem */
533     Bool elemIsCached;
535     /* elem == NULL -> start at the head */
536     if (elem == NULL) {
537         /* Keep track of whether an extra Cache_inv is needed */
538         elemIsCached = obj->cacheEnabled;
539         elem = (ListMP_Elem *)&(obj->attrs->head);
541     }
542     else {
543         elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
544     }
546     if (elemIsCached) {
547         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
548     }
550     retElem = SharedRegion_getPtr(elem->next);
552     if (retElem == (ListMP_Elem *)(&obj->attrs->head)) {
553         retElem = NULL;
554     }
556     if (elemIsCached) {
557         /* Invalidate because elem pulled into cache && elem != head. */
558         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
559     }
561     return (retElem);
564 /*
565  *  ======== ListMP_prev ========
566  */
567 Ptr ListMP_prev(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         elemIsCached = obj->cacheEnabled;
576         elem = (ListMP_Elem *)&(obj->attrs->head);
577     }
578     else {
579         elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
580     }
582     if (elemIsCached) {
583         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
584     }
586     retElem = SharedRegion_getPtr(elem->prev);
588     if (retElem == (ListMP_Elem *)(&(obj->attrs->head))) {
589         retElem = NULL;
590     }
592     if (elemIsCached) {
593         /* Invalidate because elem pulled into cache && elem != head. */
594         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
595     }
597     return (retElem);
600 /*
601  *  ======== ListMP_putHead ========
602  */
603 Int ListMP_putHead(ListMP_Handle handle, ListMP_Elem *elem)
605     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
606     UInt key;
607     UInt16 id;
608     ListMP_Elem *localNextElem;
609     SharedRegion_SRPtr sharedElem;
610     SharedRegion_SRPtr sharedHead;
611     Bool localNextElemIsCached;
613     /* prevent another thread or processor from modifying the ListMP */
614     key = GateMP_enter((GateMP_Handle)obj->gate);
616     id = SharedRegion_getId(elem);
617     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
618         sharedElem = (SharedRegion_SRPtr)elem;
619         sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head);
620         localNextElem = (ListMP_Elem *)obj->attrs->head.next;
621     }
622     else {
623         sharedElem = SharedRegion_getSRPtr(elem, id);
624         sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId);
625         localNextElem = SharedRegion_getPtr(obj->attrs->head.next);
626     }
628     /* Assert that pointer is not NULL */
629     Assert_isTrue(localNextElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
631     localNextElemIsCached = SharedRegion_isCacheEnabled(
632         SharedRegion_getId(localNextElem));
633     if (localNextElemIsCached) {
634         Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
635     }
637     /* add the new elem into the list */
638     elem->next = obj->attrs->head.next;
639     elem->prev = sharedHead;
640     localNextElem->prev = sharedElem;
641     obj->attrs->head.next = sharedElem;
643     if (localNextElemIsCached) {
644         /* Write-back because localNextElem->prev changed */
645         Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
646     }
647     if (obj->cacheEnabled) {
648         /* Write-back because obj->attrs->head.next changed */
649         Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL,
650                     TRUE);
651     }
652     if (SharedRegion_isCacheEnabled(id)) {
653         /* Write-back because elem->next & elem->prev changed */
654         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
655     }
657     GateMP_leave((GateMP_Handle)obj->gate, key);
659     return (ListMP_S_SUCCESS);
662 /*
663  *  ======== ListMP_putTail ========
664  */
665 Int ListMP_putTail(ListMP_Handle handle, ListMP_Elem *elem)
667     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
668     UInt key;
669     UInt16  id;
670     ListMP_Elem *localPrevElem;
671     SharedRegion_SRPtr sharedElem;
672     SharedRegion_SRPtr sharedHead;
673     Bool localPrevElemIsCached;
675     /* prevent another thread or processor from modifying the ListMP */
676     key = GateMP_enter((GateMP_Handle)obj->gate);
678     id = SharedRegion_getId(elem);
679     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
680         sharedElem = (SharedRegion_SRPtr)elem;
681         sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head);
682         localPrevElem = (ListMP_Elem *)obj->attrs->head.prev;
683     }
684     else {
685         sharedElem = SharedRegion_getSRPtr(elem, id);
686         sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId);
687         localPrevElem = SharedRegion_getPtr(obj->attrs->head.prev);
688     }
690     /* Assert that pointer is not NULL */
691     Assert_isTrue(localPrevElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
693     localPrevElemIsCached = SharedRegion_isCacheEnabled(
694         SharedRegion_getId(localPrevElem));
695     if (localPrevElemIsCached) {
696         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
697     }
699     /* add the new elem into the list */
700     elem->next = sharedHead;
701     elem->prev = obj->attrs->head.prev;
702     localPrevElem->next = sharedElem;
703     obj->attrs->head.prev = sharedElem;
705     if (localPrevElemIsCached) {
706         /* Write-back because localPrevElem->next changed */
707         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
708     }
709     if (obj->cacheEnabled) {
710         /* Write-back because obj->attrs->head.prev changed */
711         Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL,
712                 TRUE);
713     }
714     if (SharedRegion_isCacheEnabled(id)) {
715         /* Write-back because elem->next & elem->prev changed */
716         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
717     }
719     GateMP_leave((GateMP_Handle)obj->gate, key);
721     return (ListMP_S_SUCCESS);
724 /*
725  *  ======== ListMP_remove ========
726  */
727 Int ListMP_remove(ListMP_Handle handle, ListMP_Elem *elem)
729     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
730     UInt key;
731     ListMP_Elem *localPrevElem;
732     ListMP_Elem *localNextElem;
733     Bool localPrevElemIsCached, localNextElemIsCached;
735     /* Prevent another thread or processor from modifying the ListMP */
736     key = GateMP_enter((GateMP_Handle)obj->gate);
738     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
739         localPrevElem = (ListMP_Elem *)(elem->prev);
740         localNextElem = (ListMP_Elem *)(elem->next);
741     }
742     else {
743         localPrevElem = SharedRegion_getPtr(elem->prev);
744         localNextElem = SharedRegion_getPtr(elem->next);
745     }
747     localPrevElemIsCached = SharedRegion_isCacheEnabled(
748             SharedRegion_getId(localPrevElem));
749     localNextElemIsCached = SharedRegion_isCacheEnabled(
750             SharedRegion_getId(localNextElem));
752     if (localPrevElemIsCached) {
753         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
754     }
755     if (localNextElemIsCached) {
756         Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
757     }
759     localPrevElem->next = elem->next;
760     localNextElem->prev = elem->prev;
762     if (localPrevElemIsCached) {
763         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
764     }
765     if (localNextElemIsCached) {
766         Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
767     }
769     GateMP_leave((GateMP_Handle)obj->gate, key);
771     return (ListMP_S_SUCCESS);
774 /*
775  *************************************************************************
776  *                       Instance functions
777  *************************************************************************
778  */
780 /*
781  *  ======== ti_sdo_ipc_ListMP_Instance_init ========
782  */
783 Int ti_sdo_ipc_ListMP_Instance_init(ti_sdo_ipc_ListMP_Object *obj,
784         const ti_sdo_ipc_ListMP_Params *params,
785         Error_Block *eb)
787     SharedRegion_SRPtr sharedShmBase;
788     Ptr localAddr;
789     Int status;
790     ListMP_Params sparams;
791     IHeap_Handle regionHeap;
793     if (params->openFlag == TRUE) {
794         /* Open by sharedAddr */
795         obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC;
796         obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
797         obj->regionId = SharedRegion_getId(&(obj->attrs->head));
798         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
799         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
801         /* get the local address of the SRPtr */
802         localAddr = SharedRegion_getPtr(obj->attrs->gateMPAddr);
804         status = GateMP_openByAddr(localAddr, (GateMP_Handle *)&(obj->gate));
805         if (status != GateMP_S_SUCCESS) {
806             Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
807             return (1);
808         }
810         return (0);
811     }
813     /* init the gate */
814     if (params->gate != NULL) {
815         obj->gate = params->gate;
816     }
817     else {
818         obj->gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
819     }
821     if (params->sharedAddr == NULL) {
822         /* Creating using a shared region ID */
823         obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION;
824         obj->regionId = params->regionId;
825         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
826         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
828         /* Need to allocate from the heap */
829         ListMP_Params_init(&sparams);
830         sparams.regionId = params->regionId;
831         obj->allocSize = ListMP_sharedMemReq(&sparams);
833         regionHeap = SharedRegion_getHeap(obj->regionId);
834         Assert_isTrue(regionHeap != NULL, ti_sdo_ipc_SharedRegion_A_noHeap);
836         /* The region heap will take care of the alignment */
837         obj->attrs = Memory_alloc(regionHeap, obj->allocSize, 0, eb);
839         if (obj->attrs == NULL) {
840             return (2);
841         }
842     }
843     else {
844         /* Creating using sharedAddr */
845         obj->regionId = SharedRegion_getId(params->sharedAddr);
847         /* Assert that the buffer is in a valid shared region */
848         Assert_isTrue(obj->regionId != SharedRegion_INVALIDREGIONID,
849                       ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
851         /* set object's cacheEnabled, objType, and attrs  */
852         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
853         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
854         obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC;
855         obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
857         /* Assert that sharedAddr is cache aligned */
858         Assert_isTrue((obj->cacheLineSize == 0) ||
859                       ((UInt32)params->sharedAddr % obj->cacheLineSize == 0),
860                       ti_sdo_ipc_Ipc_A_addrNotCacheAligned);
861     }
863     /* init the head (to be empty) */
864     ListMP_elemClear(&(obj->attrs->head));
866     /* store the GateMP sharedAddr in the Attrs */
867     obj->attrs->gateMPAddr = ti_sdo_ipc_GateMP_getSharedAddr(obj->gate);
869     /* last thing, set the status */
870     obj->attrs->status = ti_sdo_ipc_ListMP_CREATED;
872     if (obj->cacheEnabled) {
873         Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
874                 Cache_Type_ALL, TRUE);
875     }
877     /* add to NameServer if name not NULL */
878     if (params->name != NULL) {
879         sharedShmBase = SharedRegion_getSRPtr(obj->attrs, obj->regionId);
880         obj->nsKey = NameServer_addUInt32(
881             (NameServer_Handle)ListMP_module->nameServer, params->name,
882             (UInt32)sharedShmBase);
884         if (obj->nsKey == NULL) {
885             Error_raise(eb, ti_sdo_ipc_Ipc_E_nameFailed, params->name, 0);
886             return (3);
887         }
888     }
890     return (0);
893 /*
894  *  ======== ti_sdo_ipc_ListMP_Instance_finalize ========
895  */
896 Void ti_sdo_ipc_ListMP_Instance_finalize(ti_sdo_ipc_ListMP_Object *obj,
897         Int status)
899     if (obj->objType & (ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC |
900                         ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION)) {
901         /* List is being deleted */
902         /* Remove entry from NameServer */
903         if (obj->nsKey != NULL) {
904             NameServer_removeEntry((NameServer_Handle)ListMP_module->nameServer,
905                     obj->nsKey);
906         }
908         /* Set status to 'not created' */
909         if (obj->attrs != NULL) {
910             obj->attrs->status = 0;
911             if (obj->cacheEnabled == TRUE) {
912                 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
913                     Cache_Type_ALL, TRUE);
914             }
915         }
917         /*
918          *  Free the shared memory back to the region heap. If NULL, then the
919          *  Memory_alloc failed.
920          */
921         if (obj->objType == ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION &&
922             obj->attrs != NULL) {
923             Memory_free(SharedRegion_getHeap(obj->regionId), obj->attrs,
924                         obj->allocSize);
925         }
926     }
927     else {
928         /* List is being closed */
929         /* Close the gate. If NULL, then GateMP_openByAddr failed. */
930         if (obj->gate != NULL) {
931             GateMP_close((GateMP_Handle *)&(obj->gate));
932         }
933     }
936 /*
937  *************************************************************************
938  *                       Module functions
939  *************************************************************************
940  */
941 /*
942  *  ======== ti_sdo_ipc_ListMP_elemClear ========
943  */
944 Void ti_sdo_ipc_ListMP_elemClear(ti_sdo_ipc_ListMP_Elem *elem)
946     SharedRegion_SRPtr sharedElem;
947     UInt16 id;
949     id = SharedRegion_getId(elem);
950     sharedElem = SharedRegion_getSRPtr(elem, id);
952     elem->next = elem->prev = sharedElem;
953     if (SharedRegion_isCacheEnabled(id)) {
954         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
955     }