]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - packages/ti/sdo/ipc/Ipc.c
Android: Added new files for Ipc_attach phase
[ipc/ipcdev.git] / packages / ti / sdo / ipc / Ipc.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  *  ======== Ipc.c ========
34  */
36 #include <string.h>     /* for memcpy() */
38 #include <xdc/std.h>
40 #include <xdc/runtime/Error.h>
41 #include <xdc/runtime/Assert.h>
42 #include <xdc/runtime/Memory.h>
43 #include <xdc/runtime/Startup.h>
45 #include <ti/sysbios/BIOS.h>
46 #include <ti/sysbios/hal/Cache.h>
47 #include <ti/sysbios/hal/Hwi.h>
48 #include <ti/sysbios/knl/Task.h>
50 #include <ti/sdo/ipc/_Ipc.h>
51 #include <ti/sdo/ipc/_Notify.h>
52 #include <ti/sdo/ipc/_GateMP.h>
53 #include <ti/sdo/ipc/_SharedRegion.h>
54 #include <ti/sdo/utils/_MultiProc.h>
55 #include <ti/sdo/utils/_NameServer.h>
56 #include <ti/sdo/ipc/_MessageQ.h>
58 #include "package/internal/Ipc.xdc.h"
60 #ifdef __ti__
61     #pragma FUNC_EXT_CALLED(Ipc_attach);
62     #pragma FUNC_EXT_CALLED(Ipc_clusterConfig);
63     #pragma FUNC_EXT_CALLED(Ipc_detach);
64     #pragma FUNC_EXT_CALLED(Ipc_isAttached);
65     #pragma FUNC_EXT_CALLED(Ipc_readConfig);
66     #pragma FUNC_EXT_CALLED(Ipc_start);
67     #pragma FUNC_EXT_CALLED(Ipc_stop);
68     #pragma FUNC_EXT_CALLED(Ipc_writeConfig);
69 #endif
71 /*
72  *  For no MMU case, it should be set to TRUE always.
73  *  For MMU, it would be set by IPC link between local and HOST processors.
74  */
75 extern __FAR__ Bits32 Ipc_sr0MemorySetup;
77 /*
78  *************************************************************************
79  *                       Common Header Functions
80  *************************************************************************
81  */
83 /*
84  *  ======== Ipc_attach ========
85  */
86 Int Ipc_attach(UInt16 remoteProcId)
87 {
88     Int i;
89     Ptr sharedAddr;
90     SizeT memReq;
91     volatile ti_sdo_ipc_Ipc_Reserved *slave;
92     ti_sdo_ipc_Ipc_ProcEntry *ipc;
93     Error_Block eb;
94     SharedRegion_Entry entry;
95     SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc();
96     Bool cacheEnabled = SharedRegion_isCacheEnabled(0);
97     UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId);
98     Int status;
99     UInt hwiKey;
101     /* Assert remoteProcId is in our cluster and isn't our own */
102     Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster,
103                   ti_sdo_utils_MultiProc_A_invalidMultiProcId);
104     Assert_isTrue(remoteProcId != MultiProc_self(),
105                   ti_sdo_ipc_Ipc_A_invArgument);
107     /* Check whether Ipc_start has been called.  If not, fail. */
108     if (Ipc_module->ipcSharedAddr == NULL) {
109         return (Ipc_E_FAIL);
110     }
112     /* for checking and incrementing attached below */
113     hwiKey = Hwi_disable();
115     /* Make sure its not already attached */
116     if (Ipc_module->procEntry[clusterId].attached) {
117         Ipc_module->procEntry[clusterId].attached++;
118         /* restore interrupts and return */
119         Hwi_restore(hwiKey);
120         return (Ipc_S_ALREADYSETUP);
121     }
123     /* restore interrupts */
124     Hwi_restore(hwiKey);
126     /* get region 0 information */
127     SharedRegion_getEntry(0, &entry);
129     /* Make sure we've attached to owner of SR0 if we're not owner */
130     if ((MultiProc_self() != entry.ownerProcId) &&
131         (remoteProcId != entry.ownerProcId) &&
132         !(Ipc_module->procEntry[ti_sdo_utils_MultiProc_getClusterId(
133             entry.ownerProcId)].attached)) {
134         return (Ipc_E_FAIL);
135     }
137     /* Init error block */
138     Error_init(&eb);
140     /* determine the slave's slot */
141     slave = Ipc_getSlaveAddr(remoteProcId, Ipc_module->ipcSharedAddr);
143     if (cacheEnabled) {
144         Cache_inv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE);
145     }
147     /* Synchronize the processors. */
148     status = Ipc_procSyncStart(remoteProcId, Ipc_module->ipcSharedAddr);
149     if (status < 0) {
150         return (status);
151     }
153     /* must be called before SharedRegion_attach */
154     status = ti_sdo_ipc_GateMP_attach(remoteProcId,
155             Ipc_module->gateMPSharedAddr);
156     if (status < 0) {
157         return (status);
158     }
160     /* retrieves the SharedRegion Heap handles */
161     status = ti_sdo_ipc_SharedRegion_attach(remoteProcId);
162     if (status < 0) {
163         return (status);
164     }
166     /* get the attach parameters associated with remoteProcId */
167     ipc = &(Ipc_module->procEntry[clusterId]);
169     /* attach Notify if not yet attached and specified to set internal setup */
170     if (!(Notify_intLineRegistered(remoteProcId, 0)) &&
171         (ipc->entry.setupNotify)) {
172         /* call Notify_attach */
173         memReq = Notify_sharedMemReq(remoteProcId, Ipc_module->ipcSharedAddr);
174         if (memReq != 0) {
175             if (MultiProc_self() < remoteProcId) {
176                 /*
177                  *  calloc required here due to race condition.  Its possible
178                  *  that the slave, who creates the instance, tries a sendEvent
179                  *  before the master has created its instance because the
180                  *  state of memory was enabled from a previous run.
181                  */
182                 sharedAddr = Memory_calloc(SharedRegion_getHeap(0),
183                                        memReq,
184                                        SharedRegion_getCacheLineSize(0),
185                                        &eb);
187                 /* make sure alloc did not fail */
188                 if (sharedAddr == NULL) {
189                     return (Ipc_E_MEMORY);
190                 }
192                 /* if cache enabled, wbInv the calloc above */
193                 if (cacheEnabled) {
194                     Cache_wbInv(sharedAddr, memReq, Cache_Type_ALL, TRUE);
195                 }
197                 /* set the notify SRPtr */
198                 slave->notifySRPtr = SharedRegion_getSRPtr(sharedAddr, 0);
199             }
200             else {
201                 /* get the notify SRPtr */
202                 sharedAddr = SharedRegion_getPtr(slave->notifySRPtr);
203             }
204         }
205         else {
206             sharedAddr = NULL;
207             if (MultiProc_self() < remoteProcId) {
208                 slave->notifySRPtr = SharedRegion_invalidSRPtr();
209             }
210         }
212         /* call attach to remote processor */
213         status = Notify_attach(remoteProcId, sharedAddr);
215         if (status < 0) {
216             if (MultiProc_self() < remoteProcId && sharedAddr != NULL) {
217                 /* free the memory back to SharedRegion 0 heap */
218                 Memory_free(SharedRegion_getHeap(0), sharedAddr, memReq);
219             }
221             return (Ipc_E_FAIL);
222         }
223     }
225     /* Must come after GateMP_start because depends on default GateMP */
226     if (!(ti_sdo_utils_NameServer_isRegistered(remoteProcId)) &&
227         (ipc->entry.setupNotify)) {
228         memReq = ti_sdo_utils_NameServer_SetupProxy_sharedMemReq(
229             Ipc_module->ipcSharedAddr);
230         if (memReq != 0) {
231             if (MultiProc_self() < remoteProcId) {
232                 sharedAddr = Memory_alloc(SharedRegion_getHeap(0),
233                                      memReq,
234                                      SharedRegion_getCacheLineSize(0),
235                                      &eb);
237                 /* make sure alloc did not fail */
238                 if (sharedAddr == NULL) {
239                     return (Ipc_E_MEMORY);
240                 }
242                 /* set the NSRN SRPtr */
243                 slave->nsrnSRPtr = SharedRegion_getSRPtr(sharedAddr, 0);
244             }
245             else {
246                 /* get the NSRN SRPtr */
247                 sharedAddr = SharedRegion_getPtr(slave->nsrnSRPtr);
248             }
249         }
250         else {
251             sharedAddr = NULL;
252             if (MultiProc_self() < remoteProcId) {
253                 slave->nsrnSRPtr = SharedRegion_invalidSRPtr();
254             }
255         }
257         /* call attach to remote processor */
258         status = ti_sdo_utils_NameServer_SetupProxy_attach(remoteProcId,
259                                                            sharedAddr);
261         if (status < 0) {
262             if (MultiProc_self() < remoteProcId && sharedAddr != NULL) {
263                 /* free the memory back to SharedRegion 0 heap */
264                 Memory_free(SharedRegion_getHeap(0), sharedAddr, memReq);
265             }
267             return (Ipc_E_FAIL);
268         }
269     }
271     /* Must come after GateMP_start because depends on default GateMP */
272     if (!(ti_sdo_ipc_MessageQ_SetupTransportProxy_isRegistered(remoteProcId)) &&
273         (ipc->entry.setupMessageQ)) {
274         memReq = ti_sdo_ipc_MessageQ_SetupTransportProxy_sharedMemReq(
275             Ipc_module->ipcSharedAddr);
277         if (memReq != 0) {
278             if (MultiProc_self() < remoteProcId) {
279                 sharedAddr = Memory_alloc(SharedRegion_getHeap(0),
280                     memReq, SharedRegion_getCacheLineSize(0), &eb);
282                 /* make sure alloc did not fail */
283                 if (sharedAddr == NULL) {
284                     return (Ipc_E_MEMORY);
285                 }
287                 /* set the transport SRPtr */
288                 slave->transportSRPtr = SharedRegion_getSRPtr(sharedAddr, 0);
289             }
290             else {
291                 /* get the transport SRPtr */
292                 sharedAddr = SharedRegion_getPtr(slave->transportSRPtr);
293             }
294         }
295         else {
296             sharedAddr = NULL;
297             if (MultiProc_self() < remoteProcId) {
298                 slave->transportSRPtr = SharedRegion_invalidSRPtr();
299             }
300         }
302         /* call attach to remote processor */
303         status = ti_sdo_ipc_MessageQ_SetupTransportProxy_attach(remoteProcId,
304             sharedAddr);
306         if (status < 0) {
307             if (MultiProc_self() < remoteProcId && sharedAddr != NULL) {
308                 /* free the memory back to SharedRegion 0 heap */
309                 Memory_free(SharedRegion_getHeap(0), sharedAddr, memReq);
310             }
312             return (Ipc_E_FAIL);
313         }
314     }
316     /* writeback invalidate slave's shared memory if cache enabled */
317     if (cacheEnabled) {
318         if (MultiProc_self() < remoteProcId) {
319             Cache_wbInv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE);
320         }
321     }
323     /* Call user attach fxns */
324     for (i = 0; i < ti_sdo_ipc_Ipc_numUserFxns; i++) {
325         if (ti_sdo_ipc_Ipc_userFxns[i].userFxn.attach) {
326             status = ti_sdo_ipc_Ipc_userFxns[i].userFxn.attach(
327                 ti_sdo_ipc_Ipc_userFxns[i].arg, remoteProcId);
329             if (status < 0) {
330                 return (status);
331             }
332         }
333     }
335     /* Finish the processor synchronization */
336     status = ti_sdo_ipc_Ipc_procSyncFinish(remoteProcId,
337         Ipc_module->ipcSharedAddr);
339     if (status < 0) {
340         return (status);
341     }
343     /* for atomically incrementing attached */
344     hwiKey = Hwi_disable();
346     /* now attached to remote processor */
347     Ipc_module->procEntry[clusterId].attached++;
349     /* restore interrupts */
350     Hwi_restore(hwiKey);
352     return (status);
355 /*
356  *  ======== Ipc_clusterConfig ========
357  */
358 Int Ipc_clusterConfig(Void)
360     UInt16 *procIdPtr;
361     UInt16 numProcs;
362     UInt16 baseId;
363     UInt16 i;
366     /* sanity check the cluster baseId */
367     baseId = MultiProc_getBaseIdOfCluster();
369     if (baseId == MultiProc_INVALIDID) {
370         return (Ipc_E_INVALIDSTATE);
371     }
373     /* initialize the MultiProc.clusterProcList array */
374     numProcs = MultiProc_getNumProcsInCluster();
375     procIdPtr = MultiProc_getClusterProcList();
377     for (i = 0; i < numProcs; i++) {
378         *procIdPtr++ = baseId + i;
379     }
381     /* update the Ipc.procEntry[] array with valid procIds */
382     for (i = 0; i < numProcs; i++) {
383         Ipc_module->procEntry[i].entry.remoteProcId = baseId + i;
384     }
386     return (Ipc_S_SUCCESS);
389 /*
390  *  ======== Ipc_isAttached ========
391  */
392 Bool Ipc_isAttached(UInt16 remoteProcId)
394     UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId);
396     /* Assert remoteProcId is in our cluster */
397     Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster,
398                   ti_sdo_utils_MultiProc_A_invalidMultiProcId);
400     if (remoteProcId == MultiProc_self()) {
401         return (FALSE);
402     }
403     else {
404         return (Ipc_module->procEntry[clusterId].attached);
405     }
408 /*
409  *  ======== Ipc_detach ========
410  */
411 Int Ipc_detach(UInt16 remoteProcId)
413     Int i;
414     UInt16 baseId = MultiProc_getBaseIdOfCluster();
415     UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId);
416     Ptr notifySharedAddr;
417     Ptr nsrnSharedAddr;
418     Ptr msgqSharedAddr;
419     volatile ti_sdo_ipc_Ipc_Reserved *slave, *master;
420     SharedRegion_Entry entry;
421     ti_sdo_ipc_Ipc_ProcEntry *ipc;
422     SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc();
423     Bool cacheEnabled = SharedRegion_isCacheEnabled(0);
424     Int status = Ipc_S_SUCCESS;
425     UInt hwiKey;
427     /* Assert remoteProcId is in our cluster and isn't our own */
428     Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster,
429                   ti_sdo_utils_MultiProc_A_invalidMultiProcId);
430     Assert_isTrue(remoteProcId != MultiProc_self(),
431                   ti_sdo_ipc_Ipc_A_invArgument);
433     /* for checking and incrementing attached below */
434     hwiKey = Hwi_disable();
436     if (Ipc_module->procEntry[clusterId].attached > 1) {
437         /* only detach if attach count reaches 1 */
438         Ipc_module->procEntry[clusterId].attached--;
439         Hwi_restore(hwiKey);
440         return (Ipc_S_BUSY);
441     }
442     else if (Ipc_module->procEntry[clusterId].attached == 0) {
443         /* already detached, restore interrupts and return success */
444         Hwi_restore(hwiKey);
445         return (Ipc_S_SUCCESS);
446     }
448     /* restore interrupts */
449     Hwi_restore(hwiKey);
451     /* get region 0 information */
452     SharedRegion_getEntry(0, &entry);
454     /*
455      *  Make sure we detach from all other procs in cluster before
456      *  detaching from owner of SR 0.
457      */
458     if (remoteProcId == entry.ownerProcId) {
459         for (i = 0; i < ti_sdo_utils_MultiProc_numProcsInCluster; i++, baseId++) {
460             if ((baseId != MultiProc_self()) && (baseId != entry.ownerProcId) &&
461                 (Ipc_module->procEntry[i].attached)) {
462                 return (Ipc_E_FAIL);
463             }
464         }
465     }
467     /* get the paramters associated with remoteProcId */
468     ipc = &(Ipc_module->procEntry[clusterId]);
470     /* determine the slave's slot */
471     slave = Ipc_getSlaveAddr(remoteProcId, Ipc_module->ipcSharedAddr);
473     /* determine the master's slot */
474     master = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId,
475         Ipc_module->ipcSharedAddr);
477     if (cacheEnabled) {
478         Cache_inv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE);
479         Cache_inv((Ptr)master, reservedSize, Cache_Type_ALL, TRUE);
480     }
482     if (MultiProc_self() < remoteProcId) {
483         /* check to make sure master is not trying to attach */
484         if (master->startedKey == ti_sdo_ipc_Ipc_PROCSYNCSTART) {
485             return (Ipc_E_NOTREADY);
486         }
487     }
488     else {
489         /* check to make sure slave is not trying to attach */
490         if (slave->startedKey == ti_sdo_ipc_Ipc_PROCSYNCSTART) {
491             return (Ipc_E_NOTREADY);
492         }
493     }
495     /* The slave processor waits for master to finish its detach sequence */
496     if (MultiProc_self() < remoteProcId) {
497         if (master->startedKey != ti_sdo_ipc_Ipc_PROCSYNCDETACH) {
498             return (Ipc_E_NOTREADY);
499         }
500     }
502     /* Call user detach fxns */
503     for (i = 0; i < ti_sdo_ipc_Ipc_numUserFxns; i++) {
504         if (ti_sdo_ipc_Ipc_userFxns[i].userFxn.detach) {
505             status = ti_sdo_ipc_Ipc_userFxns[i].userFxn.detach(
506                 ti_sdo_ipc_Ipc_userFxns[i].arg, remoteProcId);
508             if (status < 0) {
509                 return (status);
510             }
511         }
512     }
514     if ((ipc->entry.setupMessageQ) &&
515        (ti_sdo_ipc_MessageQ_SetupTransportProxy_isRegistered(remoteProcId))) {
516         /* call MessageQ_detach for remote processor */
517         status = ti_sdo_ipc_MessageQ_SetupTransportProxy_detach(remoteProcId);
518         if (status < 0) {
519             return (Ipc_E_FAIL);
520         }
522         if (slave->transportSRPtr) {
523             /* free the memory if slave processor */
524             if (MultiProc_self() < remoteProcId) {
525                 /* get the pointer to MessageQ transport instance */
526                 msgqSharedAddr = SharedRegion_getPtr(slave->transportSRPtr);
528                 /* free the memory back to SharedRegion 0 heap */
529                 Memory_free(SharedRegion_getHeap(0),
530                     msgqSharedAddr,
531                     ti_sdo_ipc_MessageQ_SetupTransportProxy_sharedMemReq(
532                         msgqSharedAddr));
534                 /* set pointer for MessageQ transport instance to INVALID */
535                 slave->transportSRPtr = SharedRegion_invalidSRPtr();
536             }
537         }
538     }
540     if ((ipc->entry.setupNotify) &&
541         (ti_sdo_utils_NameServer_isRegistered(remoteProcId))) {
542         /* call NameServer_SetupProxy_detach for remote processor */
543         status = ti_sdo_utils_NameServer_SetupProxy_detach(remoteProcId);
544         if (status < 0) {
545             return (Ipc_E_FAIL);
546         }
548         if (slave->nsrnSRPtr) {
549             /* free the memory if slave processor */
550             if (MultiProc_self() < remoteProcId) {
551                 /* get the pointer to NSRN instance */
552                 nsrnSharedAddr = SharedRegion_getPtr(slave->nsrnSRPtr);
554                 /* free the memory back to SharedRegion 0 heap */
555                 Memory_free(SharedRegion_getHeap(0),
556                             nsrnSharedAddr,
557                             ti_sdo_utils_NameServer_SetupProxy_sharedMemReq(
558                                 nsrnSharedAddr));
560                 /* set pointer for NSRN instance to INVALID */
561                 slave->nsrnSRPtr = SharedRegion_invalidSRPtr();
562             }
563         }
564     }
566     if ((ipc->entry.setupNotify) &&
567         (Notify_intLineRegistered(remoteProcId, 0))) {
568         /* call Notify_detach for remote processor */
569         status = ti_sdo_ipc_Notify_detach(remoteProcId);
570         if (status < 0) {
571             return (Ipc_E_FAIL);
572         }
574         if (slave->notifySRPtr) {
575             /* free the memory if slave processor */
576             if (MultiProc_self() < remoteProcId) {
577                 /* get the pointer to Notify instance */
578                 notifySharedAddr = SharedRegion_getPtr(slave->notifySRPtr);
580                 /* free the memory back to SharedRegion 0 heap */
581                 Memory_free(SharedRegion_getHeap(0),
582                             notifySharedAddr,
583                             Notify_sharedMemReq(remoteProcId, notifySharedAddr));
585                 /* set pointer for Notify instance to INVALID */
586                 slave->notifySRPtr = SharedRegion_invalidSRPtr();
587             }
588         }
589     }
591     /* close any HeapMemMP which may have been opened */
592     status = ti_sdo_ipc_SharedRegion_detach(remoteProcId);
593     if (status < 0) {
594         return (status);
595     }
597     /* close any GateMP which may have been opened */
598     status = ti_sdo_ipc_GateMP_detach(remoteProcId);
599     if (status < 0) {
600         return (status);
601     }
603     if (MultiProc_self() < remoteProcId) {
604         slave->configListHead = ti_sdo_ipc_SharedRegion_INVALIDSRPTR;
605         slave->startedKey = ti_sdo_ipc_Ipc_PROCSYNCDETACH;
606         if (cacheEnabled) {
607             Cache_wbInv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE);
608         }
609     }
610     else {
611         master->configListHead = ti_sdo_ipc_SharedRegion_INVALIDSRPTR;
612         master->startedKey = ti_sdo_ipc_Ipc_PROCSYNCDETACH;
613         if (cacheEnabled) {
614             Cache_wbInv((Ptr)master, reservedSize, Cache_Type_ALL, TRUE);
615         }
616     }
618     /* attached must be decremented atomically */
619     hwiKey = Hwi_disable();
621     /* now detached from remote processor */
622     Ipc_module->procEntry[clusterId].attached--;
624     /* restore interrupts */
625     Hwi_restore(hwiKey);
627     return (status);
630 /*
631  *  ======== Ipc_readConfig ========
632  */
633 Int Ipc_readConfig(UInt16 remoteProcId, UInt32 tag, Ptr cfg, SizeT size)
635     Int status = Ipc_E_FAIL;
636     UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId);
637     volatile ti_sdo_ipc_Ipc_ConfigEntry *entry;
638     Bool cacheEnabled = SharedRegion_isCacheEnabled(0);
640     /* Assert that the remoteProc in our cluster and isn't our own */
641     Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster,
642                   ti_sdo_utils_MultiProc_A_invalidMultiProcId);
644     if (cacheEnabled) {
645         Cache_inv(Ipc_module->procEntry[clusterId].remoteConfigList,
646                   SharedRegion_getCacheLineSize(0),
647                   Cache_Type_ALL,
648                   TRUE);
649     }
651     entry = (ti_sdo_ipc_Ipc_ConfigEntry *)
652             *Ipc_module->procEntry[clusterId].remoteConfigList;
654     while ((SharedRegion_SRPtr)entry != ti_sdo_ipc_SharedRegion_INVALIDSRPTR) {
655         entry = (ti_sdo_ipc_Ipc_ConfigEntry *)
656                 SharedRegion_getPtr((SharedRegion_SRPtr)entry);
658         /* Traverse the list to find the tag */
659         if (cacheEnabled) {
660             Cache_inv((Ptr)entry,
661                       size + sizeof(ti_sdo_ipc_Ipc_ConfigEntry),
662                       Cache_Type_ALL,
663                       TRUE);
664         }
666         if ((entry->remoteProcId == MultiProc_self()) &&
667             (entry->localProcId == remoteProcId) &&
668             (entry->tag == tag)) {
670             if (size == entry->size) {
671                 memcpy(cfg, (Ptr)((UInt32)entry + sizeof(ti_sdo_ipc_Ipc_ConfigEntry)),
672                         entry->size);
673                 return (Ipc_S_SUCCESS);
674             }
675             else {
676                 return (Ipc_E_FAIL);
677             }
678         }
680         entry = (ti_sdo_ipc_Ipc_ConfigEntry *)entry->next;
681     }
683     return (status);
686 /*
687  *  ======== Ipc_start ========
688  */
689 Int Ipc_start()
691     Int i;
692     UInt16 baseId = MultiProc_getBaseIdOfCluster();
693     SharedRegion_Entry entry;
694     Ptr ipcSharedAddr;
695     Ptr gateMPSharedAddr;
696     GateMP_Params gateMPParams;
697     Int status;
699     /* Check whether Ipc_start has been called.  If so, succeed. */
700     if (Ipc_module->ipcSharedAddr != NULL) {
701         return (Ipc_S_ALREADYSETUP);
702     }
704     if (ti_sdo_ipc_Ipc_generateSlaveDataForHost) {
705         /* get Ipc_sr0MemorySetup out of the cache */
706         Cache_inv(&Ipc_sr0MemorySetup,
707               sizeof(Ipc_sr0MemorySetup),
708               Cache_Type_ALL,
709               TRUE);
711         /* check Ipc_sr0MemorySetup variable */
712         if (Ipc_sr0MemorySetup == 0x0) {
713             return (Ipc_E_NOTREADY);
714         }
715     }
717     /* get region 0 information */
718     SharedRegion_getEntry(0, &entry);
720     /* if entry is not valid then return */
721     if (entry.isValid == FALSE) {
722         return (Ipc_E_NOTREADY);
723     }
725     /*
726      *  Need to reserve memory in region 0 for processor synchronization.
727      *  This must done before SharedRegion_start().
728      */
729     ipcSharedAddr = ti_sdo_ipc_SharedRegion_reserveMemory(
730             0, Ipc_getRegion0ReservedSize());
732     /* must reserve memory for GateMP before SharedRegion_start() */
733     gateMPSharedAddr = ti_sdo_ipc_SharedRegion_reserveMemory(0,
734             ti_sdo_ipc_GateMP_getRegion0ReservedSize());
736     /* Init params for default gate (must match those in GateMP_start()) */
737     GateMP_Params_init(&gateMPParams);
738     gateMPParams.localProtect  = GateMP_LocalProtect_TASKLET;
740     if (ti_sdo_utils_MultiProc_numProcessors > 1) {
741         gateMPParams.remoteProtect = GateMP_RemoteProtect_SYSTEM;
742     }
743     else {
744         gateMPParams.remoteProtect = GateMP_RemoteProtect_NONE;
745     }
747     /* reserve memory for default gate before SharedRegion_start() */
748     ti_sdo_ipc_SharedRegion_reserveMemory(0, GateMP_sharedMemReq(&gateMPParams));
750     /* clear the reserved memory */
751     ti_sdo_ipc_SharedRegion_clearReservedMemory();
753     /* Set shared addresses */
754     Ipc_module->ipcSharedAddr = ipcSharedAddr;
755     Ipc_module->gateMPSharedAddr = gateMPSharedAddr;
757     /* create default GateMP, must be called before SharedRegion start */
758     status = ti_sdo_ipc_GateMP_start(Ipc_module->gateMPSharedAddr);
759     if (status < 0) {
760         return (status);
761     }
763     /* create HeapMemMP in each SharedRegion */
764     status = ti_sdo_ipc_SharedRegion_start();
765     if (status < 0) {
766         return (status);
767     }
769     /* Call attach for all procs if procSync is ALL */
770     if (ti_sdo_ipc_Ipc_procSync == ti_sdo_ipc_Ipc_ProcSync_ALL) {
771         /* Must attach to owner first to get default GateMP and HeapMemMP */
772         if (MultiProc_self() != entry.ownerProcId) {
773             do {
774                 status = Ipc_attach(entry.ownerProcId);
775             } while (status == Ipc_E_NOTREADY);
777             if (status < 0) {
778                 /* Ipc_attach failed. Get out of Ipc_start */
779                 return (status);
780             }
781         }
783         /* Loop to attach to all other processors in cluster */
784         for (i = 0; i < ti_sdo_utils_MultiProc_numProcsInCluster; i++, baseId++) {
785             if ((baseId == MultiProc_self()) || (baseId == entry.ownerProcId)) {
786                 continue;
787             }
789             /* Skip the processor if there are no interrupt lines to it */
790             if (Notify_numIntLines(baseId) == 0) {
791                 continue;
792             }
794             /* call Ipc_attach for every remote processor */
795             do {
796                 status = Ipc_attach(baseId);
797             } while (status == Ipc_E_NOTREADY);
799             if (status < 0) {
800                 /* Ipc_attach failed. Get out of Ipc_start */
801                 return (status);
802             }
803         }
804     }
806     return (status);
809 /*
810  *  ======== Ipc_stop ========
811  */
812 Int Ipc_stop()
814     Int status;
816     /* clear local module state */
817     Ipc_module->gateMPSharedAddr = NULL;
818     Ipc_module->ipcSharedAddr = NULL;
820     /* reset Shared Region 0 reservedSize and heap handle */
821     ti_sdo_ipc_SharedRegion_resetInternalFields(0);
823     /* delete any HeapMemMP created by owner of SR0 */
824     status = ti_sdo_ipc_SharedRegion_stop();
825     if (status < 0) {
826         return (status);
827     }
829     /* delete default GateMP created by owner of SR0 */
830     status = ti_sdo_ipc_GateMP_stop();
831     if (status < 0) {
832         return (status);
833     }
835     /* set sr0MemorySetup back to 0 if needed by Host */
836     if ((ti_sdo_ipc_Ipc_generateSlaveDataForHost) &&
837         !(ti_sdo_ipc_Ipc_sr0MemorySetup)) {
838         Ipc_sr0MemorySetup = 0;
839         Cache_wbInv(&Ipc_sr0MemorySetup,
840               sizeof(Ipc_sr0MemorySetup),
841               Cache_Type_ALL,
842               TRUE);
843     }
845     return (Ipc_S_SUCCESS);
848 /*
849  *  ======== Ipc_writeConfig ========
850  */
851 Int Ipc_writeConfig(UInt16 remoteProcId, UInt32 tag, Ptr cfg, SizeT size)
853     Int status = Ipc_S_SUCCESS;
854     UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId);
855     SharedRegion_SRPtr curSRPtr, *prevSRPtr;
856     ti_sdo_ipc_Ipc_ConfigEntry *entry;
857     Error_Block eb;
858     Bool cacheEnabled = SharedRegion_isCacheEnabled(0);
860     /* Assert that the remoteProc in our cluster */
861     Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster,
862                   ti_sdo_utils_MultiProc_A_invalidMultiProcId);
864     Error_init(&eb);
866     if (cfg == NULL) {
867         status = Ipc_E_FAIL;
869         /* get head of local config list and set prevSRPtr to it */
870         prevSRPtr = (Ipc_module->procEntry[clusterId].localConfigList);
872         /*
873          *  When cfg is NULL, the last memory allocated from a previous
874          *  Ipc_writeConfig call with the same remoteProcId, tag, and size
875          *  is freed.
876          */
877         curSRPtr = *prevSRPtr;
879         /* loop through list of config entries until matching entry is found */
880         while (curSRPtr != ti_sdo_ipc_SharedRegion_INVALIDSRPTR) {
881             /* convert Ptr associated with curSRPtr */
882             entry = (ti_sdo_ipc_Ipc_ConfigEntry *)
883                     (SharedRegion_getPtr(curSRPtr));
885             /* make sure entry matches remoteProcId, tag, and size */
886             if ((entry->remoteProcId == remoteProcId) &&
887                 (entry->tag == tag) &&
888                 (entry->size == size)) {
889                 /* Update the 'prev' next ptr */
890                 *prevSRPtr = (SharedRegion_SRPtr)entry->next;
892                 /* writeback the 'prev' ptr */
893                 if (cacheEnabled) {
894                     Cache_wb(prevSRPtr,
895                         sizeof(ti_sdo_ipc_Ipc_ConfigEntry),
896                         Cache_Type_ALL,
897                         FALSE);
898                 }
900                 /* free entry's memory back to shared heap */
901                 Memory_free(SharedRegion_getHeap(0),
902                     entry,
903                     size + sizeof(ti_sdo_ipc_Ipc_ConfigEntry));
905                 /* set the status to success */
906                 status = Ipc_S_SUCCESS;
907                 break;
908             }
910             /* set the 'prev' to the 'cur' SRPtr */
911             prevSRPtr = (SharedRegion_SRPtr *)(&entry->next);
913             /* point to next config entry */
914             curSRPtr = (SharedRegion_SRPtr)entry->next;
915         }
917         /* return that status */
918         return (status);
919     }
921     /* Allocate memory from the shared heap (System Heap) */
922     entry = Memory_alloc(SharedRegion_getHeap(0),
923                          size + sizeof(ti_sdo_ipc_Ipc_ConfigEntry),
924                          SharedRegion_getCacheLineSize(0),
925                          &eb);
927     if (entry == NULL) {
928         return (Ipc_E_FAIL);
929     }
931     /* set the entry */
932     entry->remoteProcId = remoteProcId;
933     entry->localProcId = MultiProc_self();
934     entry->tag = tag;
935     entry->size = size;
936     memcpy((Ptr)((UInt32)entry + sizeof(ti_sdo_ipc_Ipc_ConfigEntry)), cfg,
937                   size);
939     /* point the entry's next to the first entry in the list */
940     entry->next = *Ipc_module->procEntry[clusterId].localConfigList;
942     /* first write-back the entry if cache is enabled */
943     if (cacheEnabled) {
944         Cache_wb(entry, size + sizeof(ti_sdo_ipc_Ipc_ConfigEntry),
945                  Cache_Type_ALL,
946                  FALSE);
947     }
949     /* set the entry as the new first in the list */
950     *Ipc_module->procEntry[clusterId].localConfigList =
951         SharedRegion_getSRPtr(entry, 0);
953     /* write-back the config list */
954     if (cacheEnabled) {
955         Cache_wb(Ipc_module->procEntry[clusterId].localConfigList,
956                  SharedRegion_getCacheLineSize(0),
957                  Cache_Type_ALL,
958                  FALSE);
959     }
961     return (status);
964 /*
965  *************************************************************************
966  *                       Module Functions
967  *************************************************************************
968  */
970 /*
971  *  ======== ti_sdo_ipc_Ipc_dummy ========
972  */
973 Void ti_sdo_ipc_Ipc_dummy()
977 /*
978  *  ======== ti_sdo_ipc_Ipc_getEntry ========
979  */
980 Void ti_sdo_ipc_Ipc_getEntry(ti_sdo_ipc_Ipc_Entry *entry)
982     UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(entry->remoteProcId);
984     /* Assert remoteProcId is in our cluster */
985     Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster,
986                   ti_sdo_utils_MultiProc_A_invalidMultiProcId);
988     /* Get the setupNotify flag */
989     entry->setupNotify =
990         Ipc_module->procEntry[clusterId].entry.setupNotify;
992     /* Get the setupMessageQ flag */
993     entry->setupMessageQ =
994         Ipc_module->procEntry[clusterId].entry.setupMessageQ;
997 /*
998  *  ======== ti_sdo_ipc_Ipc_setEntry ========
999  */
1000 Void ti_sdo_ipc_Ipc_setEntry(ti_sdo_ipc_Ipc_Entry *entry)
1002     UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(entry->remoteProcId);
1004     /* Set the setupNotify flag */
1005     Ipc_module->procEntry[clusterId].entry.setupNotify =
1006         entry->setupNotify;
1008     /* Set the setupMessageQ flag */
1009     Ipc_module->procEntry[clusterId].entry.setupMessageQ =
1010         entry->setupMessageQ;
1013 /*
1014  *************************************************************************
1015  *                       Internal Functions
1016  *************************************************************************
1017  */
1019 /*
1020  *  ======== ti_sdo_ipc_Ipc_getMasterAddr ========
1021  */
1022 Ptr ti_sdo_ipc_Ipc_getMasterAddr(UInt16 remoteProcId, Ptr sharedAddr)
1024     Int slot;
1025     UInt16 masterId;
1026     volatile ti_sdo_ipc_Ipc_Reserved *master;
1027     SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc();
1029     /* determine the master's procId and slot */
1030     if (MultiProc_self() < remoteProcId) {
1031         masterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId);
1032         slot = ti_sdo_utils_MultiProc_getClusterId(MultiProc_self());
1033     }
1034     else {
1035         masterId = ti_sdo_utils_MultiProc_getClusterId(MultiProc_self());
1036         slot = ti_sdo_utils_MultiProc_getClusterId(remoteProcId);
1037     }
1039     /* determine the reserve address for master between self and remote */
1040     master = (ti_sdo_ipc_Ipc_Reserved *)((UInt32)sharedAddr +
1041              ((masterId * reservedSize) +
1042              (slot * sizeof(ti_sdo_ipc_Ipc_Reserved))));
1044     return ((Ptr)master);
1047 /*
1048  *  ======== ti_sdo_ipc_Ipc_getRegion0ReservedSize ========
1049  */
1050 SizeT ti_sdo_ipc_Ipc_getRegion0ReservedSize(Void)
1052     SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc();
1054     /* Calculate the total amount to reserve */
1055     reservedSize = reservedSize * ti_sdo_utils_MultiProc_numProcsInCluster;
1057     return (reservedSize);
1060 /*
1061  *  ======== ti_sdo_ipc_Ipc_getSlaveAddr ========
1062  */
1063 Ptr ti_sdo_ipc_Ipc_getSlaveAddr(UInt16 remoteProcId, Ptr sharedAddr)
1065     Int slot;
1066     UInt16 slaveId;
1067     volatile ti_sdo_ipc_Ipc_Reserved *slave;
1068     SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc();
1070     /* determine the slave's procId and slot */
1071     if (MultiProc_self() < remoteProcId) {
1072         slaveId = ti_sdo_utils_MultiProc_getClusterId(MultiProc_self());
1073         slot = ti_sdo_utils_MultiProc_getClusterId(remoteProcId) - 1;
1074     }
1075     else {
1076         slaveId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId);
1077         slot = ti_sdo_utils_MultiProc_getClusterId(MultiProc_self()) - 1;
1078     }
1080     /* determine the reserve address for slave between self and remote */
1081     slave = (ti_sdo_ipc_Ipc_Reserved *)((UInt32)sharedAddr +
1082             ((slaveId * reservedSize) +
1083             (slot * sizeof(ti_sdo_ipc_Ipc_Reserved))));
1085     return ((Ptr)slave);
1088 /*
1089  *  ======== ti_sdo_ipc_Ipc_procSyncStart ========
1090  *  The owner of SharedRegion 0 writes to its reserve memory address
1091  *  in region 0 to let the other processors know it has started.
1092  *  It then spins until the other processors start.
1093  *  The other processors write their reserve memory address in
1094  *  region 0 to let the owner processor know they've started.
1095  *  The other processors then spin until the owner processor writes
1096  *  to let them know that its finished the process of synchronization
1097  *  before continuing.
1098  */
1099 Int ti_sdo_ipc_Ipc_procSyncStart(UInt16 remoteProcId, Ptr sharedAddr)
1101     volatile ti_sdo_ipc_Ipc_Reserved *self, *remote;
1102     ti_sdo_ipc_Ipc_ProcEntry *ipc;
1103     UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId);
1104     SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc();
1105     Bool cacheEnabled = SharedRegion_isCacheEnabled(0);
1107     /* don't do any synchronization if procSync is NONE */
1108     if (ti_sdo_ipc_Ipc_procSync == ti_sdo_ipc_Ipc_ProcSync_NONE) {
1109         return (Ipc_S_SUCCESS);
1110     }
1112     /* determine self and remote pointers */
1113     if (MultiProc_self() < remoteProcId) {
1114         self = Ipc_getSlaveAddr(remoteProcId, sharedAddr);
1115         remote = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, sharedAddr);
1116     }
1117     else {
1118         self = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, sharedAddr);
1119         remote = Ipc_getSlaveAddr(remoteProcId, sharedAddr);
1120     }
1122     /* construct the config list */
1123     ipc = &(Ipc_module->procEntry[clusterId]);
1125     ipc->localConfigList = (Ptr)&self->configListHead;
1126     ipc->remoteConfigList = (Ptr)&remote->configListHead;
1128     *ipc->localConfigList = ti_sdo_ipc_SharedRegion_INVALIDSRPTR;
1130     if (cacheEnabled) {
1131         Cache_wbInv(ipc->localConfigList, reservedSize, Cache_Type_ALL, TRUE);
1132     }
1134     if (MultiProc_self() < remoteProcId) {
1135         /* set my processor's reserved key to start */
1136         self->startedKey = ti_sdo_ipc_Ipc_PROCSYNCSTART;
1138         /* write back my processor's reserve key */
1139         if (cacheEnabled) {
1140             Cache_wbInv((Ptr)self, reservedSize, Cache_Type_ALL, TRUE);
1141         }
1143         /* wait for remote processor to start */
1144         if (cacheEnabled) {
1145             Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE);
1146         }
1148         if (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCSTART) {
1149             return (Ipc_E_NOTREADY);
1150         }
1151     }
1152     else {
1153         /*  wait for remote processor to start */
1154         if (cacheEnabled) {
1155             Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE);
1156         }
1158         if ((self->startedKey != ti_sdo_ipc_Ipc_PROCSYNCSTART) &&
1159             (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCSTART)) {
1160             return (Ipc_E_NOTREADY);
1161         }
1163         /* set my processor's reserved key to start */
1164         self->startedKey = ti_sdo_ipc_Ipc_PROCSYNCSTART;
1166         /* write my processor's reserve key back */
1167         if (cacheEnabled) {
1168             Cache_wbInv((Ptr)self, reservedSize, Cache_Type_ALL, TRUE);
1170             /* wait for remote processor to finish */
1171             Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE);
1172         }
1174         if (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCFINISH) {
1175             return (Ipc_E_NOTREADY);
1176         }
1177     }
1179     return (Ipc_S_SUCCESS);
1182 /*
1183  *  ======== ti_sdo_ipc_Ipc_procSyncFinish ========
1184  *  Each processor writes its reserve memory address in SharedRegion 0
1185  *  to let the other processors know its finished the process of
1186  *  synchronization.
1187  */
1188 Int ti_sdo_ipc_Ipc_procSyncFinish(UInt16 remoteProcId, Ptr sharedAddr)
1190     volatile ti_sdo_ipc_Ipc_Reserved *self, *remote;
1191     SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc();
1192     Bool cacheEnabled = SharedRegion_isCacheEnabled(0);
1193     UInt oldPri;
1195     /* don't do any synchronization if procSync is NONE */
1196     if (ti_sdo_ipc_Ipc_procSync == ti_sdo_ipc_Ipc_ProcSync_NONE) {
1197         return (Ipc_S_SUCCESS);
1198     }
1200     /* determine self and remote pointers */
1201     if (MultiProc_self() < remoteProcId) {
1202         self = Ipc_getSlaveAddr(remoteProcId, sharedAddr);
1203         remote = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, sharedAddr);
1204     }
1205     else {
1206         self = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, sharedAddr);
1207         remote = Ipc_getSlaveAddr(remoteProcId, sharedAddr);
1208     }
1210     /* set my processor's reserved key to finish */
1211     self->startedKey = ti_sdo_ipc_Ipc_PROCSYNCFINISH;
1213     /* write back my processor's reserve key */
1214     if (cacheEnabled) {
1215         Cache_wbInv((Ptr)self, reservedSize, Cache_Type_ALL, TRUE);
1216     }
1218     /* if slave processor, wait for remote to finish sync */
1219     if (MultiProc_self() < remoteProcId) {
1220         if (BIOS_getThreadType() == BIOS_ThreadType_Task) {
1221             oldPri = Task_getPri(Task_self());
1222         }
1224         /* wait for remote processor to finish */
1225         while (remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCFINISH &&
1226                 remote->startedKey != ti_sdo_ipc_Ipc_PROCSYNCDETACH) {
1227             /* Set self priority to 1 [lowest] and yield cpu */
1228             if (BIOS_getThreadType() == BIOS_ThreadType_Task) {
1229                 Task_setPri(Task_self(), 1);
1230                 Task_yield();
1231             }
1233             /* Check the remote's sync flag */
1234             if (cacheEnabled) {
1235                 Cache_inv((Ptr)remote, reservedSize, Cache_Type_ALL, TRUE);
1236             }
1237         }
1239         /* Restore self priority */
1240         if (BIOS_getThreadType() == BIOS_ThreadType_Task) {
1241             Task_setPri(Task_self(), oldPri);
1242         }
1243     }
1245     return (Ipc_S_SUCCESS);
1248 /*
1249  *  ======== ti_sdo_ipc_Ipc_reservedSizePerProc ========
1250  */
1251 SizeT ti_sdo_ipc_Ipc_reservedSizePerProc(Void)
1253     SizeT reservedSize = sizeof(ti_sdo_ipc_Ipc_Reserved) *
1254             ti_sdo_utils_MultiProc_numProcsInCluster;
1255     SizeT cacheLineSize = SharedRegion_getCacheLineSize(0);
1257     /* Calculate amount to reserve per processor */
1258     if (cacheLineSize > reservedSize) {
1259         /* Use cacheLineSize if larger than reservedSize */
1260         reservedSize = cacheLineSize;
1261     }
1262     else {
1263         /* Round reservedSize to cacheLineSize */
1264         reservedSize = _Ipc_roundup(reservedSize, cacheLineSize);
1265     }
1267     return (reservedSize);