d0b9e7b0432f5ea0b543fc12f40146bf0683d046
[ipc/ipcdev.git] / packages / ti / sdo / ipc / ListMP.c
1 /*
2  * Copyright (c) 2012-2013, Texas Instruments Incorporated
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,
163                                   &sharedShmBase,
164                                   ti_sdo_utils_MultiProc_procIdList);
166     if (status < 0) {
167         /* Name was not found */
168         *handlePtr = NULL;
169         return (ListMP_E_NOTFOUND);
170     }
172     sharedAddr = SharedRegion_getPtr(sharedShmBase);
174     status = ListMP_openByAddr(sharedAddr, handlePtr);
176     return (status);
179 /*
180  *  ======== ListMP_openByAddr ========
181  */
182 Int ListMP_openByAddr(Ptr sharedAddr, ListMP_Handle *handlePtr)
184     ti_sdo_ipc_ListMP_Params params;
185     ti_sdo_ipc_ListMP_Attrs *attrs;
186     Error_Block eb;
187     Int status;
188     UInt16 id;
190     Error_init(&eb);
192     ti_sdo_ipc_ListMP_Params_init(&params);
194     /* Tell Instance_init() that we're opening */
195     params.openFlag = TRUE;
197     attrs = (ti_sdo_ipc_ListMP_Attrs *)sharedAddr;
198     params.sharedAddr = sharedAddr;
199     id = SharedRegion_getId(sharedAddr);
201     if (SharedRegion_isCacheEnabled(id)) {
202         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
203     }
205     if (attrs->status != ti_sdo_ipc_ListMP_CREATED) {
206         *handlePtr = NULL;
207         status = ListMP_E_NOTFOUND;
208     }
209     else {
210         /* Create the object */
211         *handlePtr = (ListMP_Handle)ti_sdo_ipc_ListMP_create(&params, &eb);
212         if (*handlePtr == NULL) {
213             status = ListMP_E_FAIL;
214         }
215         else {
216             status = ListMP_S_SUCCESS;
217         }
218     }
220     if (SharedRegion_isCacheEnabled(id)) {
221         Cache_inv(attrs, sizeof(ti_sdo_ipc_ListMP_Attrs), Cache_Type_ALL, TRUE);
222     }
224     return (status);
227 /*
228  *  ======== ListMP_sharedMemReq ========
229  */
230 SizeT ListMP_sharedMemReq(const ListMP_Params *params)
232     SizeT  memReq, minAlign;
233     UInt16 regionId;
235     if (params->sharedAddr == NULL) {
236         regionId = params->regionId;
237     }
238     else {
239         regionId = SharedRegion_getId(params->sharedAddr);
240     }
242     /* Assert that the region is valid */
243     Assert_isTrue(regionId != SharedRegion_INVALIDREGIONID,
244                   ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
246     minAlign = Memory_getMaxDefaultTypeAlign();
247     if (SharedRegion_getCacheLineSize(regionId) > minAlign) {
248         minAlign = SharedRegion_getCacheLineSize(regionId);
249     }
251     memReq = _Ipc_roundup(sizeof(ti_sdo_ipc_ListMP_Attrs), minAlign);
253     return (memReq);
256 /*
257  *  ======== ListMP_empty ========
258  */
259 Bool ListMP_empty(ListMP_Handle handle)
261     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
262     Bool flag = FALSE;
263     IArg key;
264     SharedRegion_SRPtr sharedHead;
266     /* prevent another thread or processor from modifying the ListMP */
267     key = GateMP_enter((GateMP_Handle)obj->gate);
270     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
271         /* get the SRPtr for the head */
272         sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head);
273     }
274     else {
275         /* get the SRPtr for the head */
276         sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId);
277     }
279     /* if 'next' is ourself, then the ListMP must be empty */
280     if (obj->attrs->head.next == sharedHead) {
281         flag = TRUE;
282     }
284     if (obj->cacheEnabled) {
285         /* invalidate the head to make sure we are not getting stale data */
286         Cache_inv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL,
287                   TRUE);
288     }
290     /* leave the gate */
291     GateMP_leave((GateMP_Handle)obj->gate, key);
293     return (flag);
296 /*
297  *  ======== ListMP_getGate ========
298  */
299 GateMP_Handle ListMP_getGate(ListMP_Handle handle)
301     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
303     return ((GateMP_Handle)obj->gate);
306 /*
307  *  ======== ListMP_getHead ========
308  */
309 Ptr ListMP_getHead(ListMP_Handle handle)
311     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
312     ListMP_Elem *elem;
313     ListMP_Elem *localHeadNext;
314     ListMP_Elem *localNext;
315     Bool localNextIsCached;
316     UInt key;
318     /* prevent another thread or processor from modifying the ListMP */
319     key = GateMP_enter((GateMP_Handle)obj->gate);
321     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
322         localHeadNext = (ListMP_Elem *)obj->attrs->head.next;
323     }
324     else {
325         localHeadNext = SharedRegion_getPtr(obj->attrs->head.next);
326     }
328     /* Assert that pointer is not NULL */
329     Assert_isTrue(localHeadNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
331     /* See if the ListMP was empty */
332     if (localHeadNext == (ListMP_Elem *)(&(obj->attrs->head))) {
333         /* Empty, return NULL */
334         elem = NULL;
335     }
336     else {
337         if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadNext))) {
338             /* invalidate elem */
339             Cache_inv(localHeadNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
340         }
342         if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
343             localNext = (ListMP_Elem *)localHeadNext->next;
344         }
345         else {
346             localNext = SharedRegion_getPtr(localHeadNext->next);
347         }
349         /* Assert that pointer is not NULL */
350         Assert_isTrue(localNext != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
352         /* Elem to return */
353         elem = localHeadNext;
354         localNextIsCached = SharedRegion_isCacheEnabled(
355                 SharedRegion_getId(localNext));
356         if (localNextIsCached) {
357             Cache_inv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
358         }
360         /* Fix the head of the list next pointer */
361         obj->attrs->head.next = elem->next;
363         /* Fix the prev pointer of the new first elem on the list */
364         localNext->prev = localHeadNext->prev;
365         if (localNextIsCached) {
366             Cache_wbInv(localNext, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
367         }
368     }
370     if (obj->cacheEnabled) {
371         Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem),
372                     Cache_Type_ALL, TRUE);
373     }
375     GateMP_leave((GateMP_Handle)obj->gate, key);
377     return (elem);
380 /*
381  *  ======== ListMP_getTail ========
382  */
383 Ptr ListMP_getTail(ListMP_Handle handle)
385     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
386     ListMP_Elem *elem;
387     ListMP_Elem *localHeadPrev;
388     ListMP_Elem *localPrev;
389     Bool localPrevIsCached;
390     UInt key;
392     /* prevent another thread or processor from modifying the ListMP */
393     key = GateMP_enter((GateMP_Handle)obj->gate);
395     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
396         localHeadPrev = (ListMP_Elem *)obj->attrs->head.prev;
397     }
398     else {
399         localHeadPrev = SharedRegion_getPtr(obj->attrs->head.prev);
400     }
402     /* Assert that pointer is not NULL */
403     Assert_isTrue(localHeadPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
405     /* See if the ListMP was empty */
406     if (localHeadPrev == (ListMP_Elem *)(&(obj->attrs->head))) {
407         /* Empty, return NULL */
408         elem = NULL;
409     }
410     else {
411         if (SharedRegion_isCacheEnabled(SharedRegion_getId(localHeadPrev))) {
412             /* invalidate elem */
413             Cache_inv(localHeadPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
414         }
416         if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
417             localPrev = (ListMP_Elem *)localHeadPrev->prev;
418         }
419         else {
420             localPrev = SharedRegion_getPtr(localHeadPrev->prev);
421         }
423         /* Assert that pointer is not NULL */
424         Assert_isTrue(localPrev != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
426         /* Elem to return */
427         elem = localHeadPrev;
428         localPrevIsCached = SharedRegion_isCacheEnabled(
429                 SharedRegion_getId(localPrev));
430         if (localPrevIsCached) {
431             Cache_inv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
432         }
434         /* Fix the head of the list prev pointer */
435         obj->attrs->head.prev = elem->prev;
437         /* Fix the next pointer of the new last elem on the list */
438         localPrev->next = localHeadPrev->next;
439         if (localPrevIsCached) {
440             Cache_wbInv(localPrev, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
441         }
442     }
444     if (obj->cacheEnabled) {
445         Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem),
446                     Cache_Type_ALL, TRUE);
447     }
449     GateMP_leave((GateMP_Handle)obj->gate, key);
451     return (elem);
454 /*
455  *  ======== ListMP_insert ========
456  */
457 Int ListMP_insert(ListMP_Handle handle, ListMP_Elem *newElem,
458                   ListMP_Elem *curElem)
460     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
461     UInt key;
462     Int  id;
463     ListMP_Elem *localPrevElem;
464     SharedRegion_SRPtr sharedNewElem;
465     SharedRegion_SRPtr sharedCurElem;
466     Bool curElemIsCached, localPrevElemIsCached;
468     /* prevent another thread or processor from modifying the ListMP */
469     key = GateMP_enter((GateMP_Handle)obj->gate);
471     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
472         sharedNewElem = (SharedRegion_SRPtr)newElem;
473         sharedCurElem = (SharedRegion_SRPtr)curElem;
474         localPrevElem = (ListMP_Elem *)(curElem->prev);
475     }
476     else {
477         /* get SRPtr for newElem */
478         id = SharedRegion_getId(newElem);
479         sharedNewElem = SharedRegion_getSRPtr(newElem, id);
481         /* get SRPtr for curElem */
482         id = SharedRegion_getId(curElem);
483         sharedCurElem = SharedRegion_getSRPtr(curElem, id);
484     }
486     curElemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(curElem));
487     if (curElemIsCached) {
488         Cache_inv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
489     }
491     /* get Ptr for curElem->prev */
492     localPrevElem = SharedRegion_getPtr(curElem->prev);
494     localPrevElemIsCached = SharedRegion_isCacheEnabled(
495             SharedRegion_getId(localPrevElem));
496     if (localPrevElemIsCached) {
497         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
498     }
500     newElem->next       = sharedCurElem;
501     newElem->prev       = curElem->prev;
502     localPrevElem->next = sharedNewElem;
503     curElem->prev       = sharedNewElem;
505     if (localPrevElemIsCached) {
506         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
507     }
509     /*
510      *  The next two Cache_wbInv needs to be done because curElem
511      *  and newElem are passed in and maybe already in the cache
512      */
513     if (curElemIsCached) {
514         /* writeback invalidate current elem structure */
515         Cache_wbInv(curElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
516     }
518     if (SharedRegion_isCacheEnabled(SharedRegion_getId(newElem))) {
519         /* writeback invalidate new elem structure  */
520         Cache_wbInv(newElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
521     }
523     GateMP_leave((GateMP_Handle)obj->gate, key);
525     return (ListMP_S_SUCCESS);
528 /*
529  *  ======== ListMP_next ========
530  */
531 Ptr ListMP_next(ListMP_Handle handle, ListMP_Elem *elem)
533     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
534     ListMP_Elem *retElem;  /* returned elem */
535     Bool elemIsCached;
537     /* elem == NULL -> start at the head */
538     if (elem == NULL) {
539         /* Keep track of whether an extra Cache_inv is needed */
540         elemIsCached = obj->cacheEnabled;
541         elem = (ListMP_Elem *)&(obj->attrs->head);
543     }
544     else {
545         elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
546     }
548     if (elemIsCached) {
549         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
550     }
552     retElem = SharedRegion_getPtr(elem->next);
554     if (retElem == (ListMP_Elem *)(&obj->attrs->head)) {
555         retElem = NULL;
556     }
558     if (elemIsCached) {
559         /* Invalidate because elem pulled into cache && elem != head. */
560         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
561     }
563     return (retElem);
566 /*
567  *  ======== ListMP_prev ========
568  */
569 Ptr ListMP_prev(ListMP_Handle handle, ListMP_Elem *elem)
571     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
572     ListMP_Elem *retElem;  /* returned elem */
573     Bool elemIsCached;
575     /* elem == NULL -> start at the head */
576     if (elem == NULL) {
577         elemIsCached = obj->cacheEnabled;
578         elem = (ListMP_Elem *)&(obj->attrs->head);
579     }
580     else {
581         elemIsCached = SharedRegion_isCacheEnabled(SharedRegion_getId(elem));
582     }
584     if (elemIsCached) {
585         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
586     }
588     retElem = SharedRegion_getPtr(elem->prev);
590     if (retElem == (ListMP_Elem *)(&(obj->attrs->head))) {
591         retElem = NULL;
592     }
594     if (elemIsCached) {
595         /* Invalidate because elem pulled into cache && elem != head. */
596         Cache_inv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
597     }
599     return (retElem);
602 /*
603  *  ======== ListMP_putHead ========
604  */
605 Int ListMP_putHead(ListMP_Handle handle, ListMP_Elem *elem)
607     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
608     UInt key;
609     UInt16 id;
610     ListMP_Elem *localNextElem;
611     SharedRegion_SRPtr sharedElem;
612     SharedRegion_SRPtr sharedHead;
613     Bool localNextElemIsCached;
615     /* prevent another thread or processor from modifying the ListMP */
616     key = GateMP_enter((GateMP_Handle)obj->gate);
618     id = SharedRegion_getId(elem);
619     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
620         sharedElem = (SharedRegion_SRPtr)elem;
621         sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head);
622         localNextElem = (ListMP_Elem *)obj->attrs->head.next;
623     }
624     else {
625         sharedElem = SharedRegion_getSRPtr(elem, id);
626         sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId);
627         localNextElem = SharedRegion_getPtr(obj->attrs->head.next);
628     }
630     /* Assert that pointer is not NULL */
631     Assert_isTrue(localNextElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
633     localNextElemIsCached = SharedRegion_isCacheEnabled(
634         SharedRegion_getId(localNextElem));
635     if (localNextElemIsCached) {
636         Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
637     }
639     /* add the new elem into the list */
640     elem->next = obj->attrs->head.next;
641     elem->prev = sharedHead;
642     localNextElem->prev = sharedElem;
643     obj->attrs->head.next = sharedElem;
645     if (localNextElemIsCached) {
646         /* Write-back because localNextElem->prev changed */
647         Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
648     }
649     if (obj->cacheEnabled) {
650         /* Write-back because obj->attrs->head.next changed */
651         Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL,
652                     TRUE);
653     }
654     if (SharedRegion_isCacheEnabled(id)) {
655         /* Write-back because elem->next & elem->prev changed */
656         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
657     }
659     GateMP_leave((GateMP_Handle)obj->gate, key);
661     return (ListMP_S_SUCCESS);
664 /*
665  *  ======== ListMP_putTail ========
666  */
667 Int ListMP_putTail(ListMP_Handle handle, ListMP_Elem *elem)
669     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
670     UInt key;
671     UInt16  id;
672     ListMP_Elem *localPrevElem;
673     SharedRegion_SRPtr sharedElem;
674     SharedRegion_SRPtr sharedHead;
675     Bool localPrevElemIsCached;
677     /* prevent another thread or processor from modifying the ListMP */
678     key = GateMP_enter((GateMP_Handle)obj->gate);
680     id = SharedRegion_getId(elem);
681     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
682         sharedElem = (SharedRegion_SRPtr)elem;
683         sharedHead = (SharedRegion_SRPtr)&(obj->attrs->head);
684         localPrevElem = (ListMP_Elem *)obj->attrs->head.prev;
685     }
686     else {
687         sharedElem = SharedRegion_getSRPtr(elem, id);
688         sharedHead = SharedRegion_getSRPtr(&(obj->attrs->head), obj->regionId);
689         localPrevElem = SharedRegion_getPtr(obj->attrs->head.prev);
690     }
692     /* Assert that pointer is not NULL */
693     Assert_isTrue(localPrevElem != NULL, ti_sdo_ipc_Ipc_A_nullPointer);
695     localPrevElemIsCached = SharedRegion_isCacheEnabled(
696         SharedRegion_getId(localPrevElem));
697     if (localPrevElemIsCached) {
698         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
699     }
701     /* add the new elem into the list */
702     elem->next = sharedHead;
703     elem->prev = obj->attrs->head.prev;
704     localPrevElem->next = sharedElem;
705     obj->attrs->head.prev = sharedElem;
707     if (localPrevElemIsCached) {
708         /* Write-back because localPrevElem->next changed */
709         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
710     }
711     if (obj->cacheEnabled) {
712         /* Write-back because obj->attrs->head.prev changed */
713         Cache_wbInv(&(obj->attrs->head), sizeof(ListMP_Elem), Cache_Type_ALL,
714                 TRUE);
715     }
716     if (SharedRegion_isCacheEnabled(id)) {
717         /* Write-back because elem->next & elem->prev changed */
718         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
719     }
721     GateMP_leave((GateMP_Handle)obj->gate, key);
723     return (ListMP_S_SUCCESS);
726 /*
727  *  ======== ListMP_remove ========
728  */
729 Int ListMP_remove(ListMP_Handle handle, ListMP_Elem *elem)
731     ti_sdo_ipc_ListMP_Object *obj = (ti_sdo_ipc_ListMP_Object *)handle;
732     UInt key;
733     ListMP_Elem *localPrevElem;
734     ListMP_Elem *localNextElem;
735     Bool localPrevElemIsCached, localNextElemIsCached;
737     /* Prevent another thread or processor from modifying the ListMP */
738     key = GateMP_enter((GateMP_Handle)obj->gate);
740     if (ti_sdo_ipc_SharedRegion_translate == FALSE) {
741         localPrevElem = (ListMP_Elem *)(elem->prev);
742         localNextElem = (ListMP_Elem *)(elem->next);
743     }
744     else {
745         localPrevElem = SharedRegion_getPtr(elem->prev);
746         localNextElem = SharedRegion_getPtr(elem->next);
747     }
749     localPrevElemIsCached = SharedRegion_isCacheEnabled(
750             SharedRegion_getId(localPrevElem));
751     localNextElemIsCached = SharedRegion_isCacheEnabled(
752             SharedRegion_getId(localNextElem));
754     if (localPrevElemIsCached) {
755         Cache_inv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
756     }
757     if (localNextElemIsCached) {
758         Cache_inv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
759     }
761     localPrevElem->next = elem->next;
762     localNextElem->prev = elem->prev;
764     if (localPrevElemIsCached) {
765         Cache_wbInv(localPrevElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
766     }
767     if (localNextElemIsCached) {
768         Cache_wbInv(localNextElem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
769     }
771     GateMP_leave((GateMP_Handle)obj->gate, key);
773     return (ListMP_S_SUCCESS);
776 /*
777  *************************************************************************
778  *                       Instance functions
779  *************************************************************************
780  */
782 /*
783  *  ======== ti_sdo_ipc_ListMP_Instance_init ========
784  */
785 Int ti_sdo_ipc_ListMP_Instance_init(ti_sdo_ipc_ListMP_Object *obj,
786         const ti_sdo_ipc_ListMP_Params *params,
787         Error_Block *eb)
789     SharedRegion_SRPtr sharedShmBase;
790     Ptr localAddr;
791     Int status;
792     ListMP_Params sparams;
793     IHeap_Handle regionHeap;
795     if (params->openFlag == TRUE) {
796         /* Open by sharedAddr */
797         obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC;
798         obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
799         obj->regionId = SharedRegion_getId(&(obj->attrs->head));
800         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
801         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
803         /* get the local address of the SRPtr */
804         localAddr = SharedRegion_getPtr(obj->attrs->gateMPAddr);
806         status = GateMP_openByAddr(localAddr, (GateMP_Handle *)&(obj->gate));
807         if (status != GateMP_S_SUCCESS) {
808             Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
809             return (1);
810         }
812         return (0);
813     }
815     /* init the gate */
816     if (params->gate != NULL) {
817         obj->gate = params->gate;
818     }
819     else {
820         obj->gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
821     }
823     if (params->sharedAddr == NULL) {
824         /* Creating using a shared region ID */
825         obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION;
826         obj->regionId = params->regionId;
827         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
828         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
830         /* Need to allocate from the heap */
831         ListMP_Params_init(&sparams);
832         sparams.regionId = params->regionId;
833         obj->allocSize = ListMP_sharedMemReq(&sparams);
835         regionHeap = SharedRegion_getHeap(obj->regionId);
836         Assert_isTrue(regionHeap != NULL, ti_sdo_ipc_SharedRegion_A_noHeap);
838         /* The region heap will take care of the alignment */
839         obj->attrs = Memory_alloc(regionHeap, obj->allocSize, 0, eb);
841         if (obj->attrs == NULL) {
842             return (2);
843         }
844     }
845     else {
846         /* Creating using sharedAddr */
847         obj->regionId = SharedRegion_getId(params->sharedAddr);
849         /* Assert that the buffer is in a valid shared region */
850         Assert_isTrue(obj->regionId != SharedRegion_INVALIDREGIONID,
851                       ti_sdo_ipc_Ipc_A_addrNotInSharedRegion);
853         /* set object's cacheEnabled, objType, and attrs  */
854         obj->cacheEnabled = SharedRegion_isCacheEnabled(obj->regionId);
855         obj->cacheLineSize = SharedRegion_getCacheLineSize(obj->regionId);
856         obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC;
857         obj->attrs = (ti_sdo_ipc_ListMP_Attrs *)params->sharedAddr;
859         /* Assert that sharedAddr is cache aligned */
860         Assert_isTrue((obj->cacheLineSize == 0) ||
861                       ((UInt32)params->sharedAddr % obj->cacheLineSize == 0),
862                       ti_sdo_ipc_Ipc_A_addrNotCacheAligned);
863     }
865     /* init the head (to be empty) */
866     ListMP_elemClear(&(obj->attrs->head));
868     /* store the GateMP sharedAddr in the Attrs */
869     obj->attrs->gateMPAddr = ti_sdo_ipc_GateMP_getSharedAddr(obj->gate);
871     /* last thing, set the status */
872     obj->attrs->status = ti_sdo_ipc_ListMP_CREATED;
874     if (obj->cacheEnabled) {
875         Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
876                 Cache_Type_ALL, TRUE);
877     }
879     /* add to NameServer if name not NULL */
880     if (params->name != NULL) {
881         sharedShmBase = SharedRegion_getSRPtr(obj->attrs, obj->regionId);
882         obj->nsKey = NameServer_addUInt32(
883             (NameServer_Handle)ListMP_module->nameServer, params->name,
884             (UInt32)sharedShmBase);
886         if (obj->nsKey == NULL) {
887             Error_raise(eb, ti_sdo_ipc_Ipc_E_nameFailed, params->name, 0);
888             return (3);
889         }
890     }
892     return (0);
895 /*
896  *  ======== ti_sdo_ipc_ListMP_Instance_finalize ========
897  */
898 Void ti_sdo_ipc_ListMP_Instance_finalize(ti_sdo_ipc_ListMP_Object *obj,
899         Int status)
901     if (obj->objType & (ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC |
902                         ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION)) {
903         /* List is being deleted */
904         /* Remove entry from NameServer */
905         if (obj->nsKey != NULL) {
906             NameServer_removeEntry((NameServer_Handle)ListMP_module->nameServer,
907                     obj->nsKey);
908         }
910         /* Set status to 'not created' */
911         if (obj->attrs != NULL) {
912             obj->attrs->status = 0;
913             if (obj->cacheEnabled == TRUE) {
914                 Cache_wbInv(obj->attrs, sizeof(ti_sdo_ipc_ListMP_Attrs),
915                     Cache_Type_ALL, TRUE);
916             }
917         }
919         /*
920          *  Free the shared memory back to the region heap. If NULL, then the
921          *  Memory_alloc failed.
922          */
923         if (obj->objType == ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC_REGION &&
924             obj->attrs != NULL) {
925             Memory_free(SharedRegion_getHeap(obj->regionId), obj->attrs,
926                         obj->allocSize);
927         }
928     }
929     else {
930         /* List is being closed */
931         /* Close the gate. If NULL, then GateMP_openByAddr failed. */
932         if (obj->gate != NULL) {
933             GateMP_close((GateMP_Handle *)&(obj->gate));
934         }
935     }
938 /*
939  *************************************************************************
940  *                       Module functions
941  *************************************************************************
942  */
943 /*
944  *  ======== ti_sdo_ipc_ListMP_elemClear ========
945  */
946 Void ti_sdo_ipc_ListMP_elemClear(ti_sdo_ipc_ListMP_Elem *elem)
948     SharedRegion_SRPtr sharedElem;
949     UInt16 id;
951     id = SharedRegion_getId(elem);
952     sharedElem = SharedRegion_getSRPtr(elem, id);
954     elem->next = elem->prev = sharedElem;
955     if (SharedRegion_isCacheEnabled(id)) {
956         Cache_wbInv(elem, sizeof(ListMP_Elem), Cache_Type_ALL, TRUE);
957     }