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);
353 }
355 /*
356 * ======== Ipc_clusterConfig ========
357 */
358 Int Ipc_clusterConfig(Void)
359 {
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);
387 }
389 /*
390 * ======== Ipc_isAttached ========
391 */
392 Bool Ipc_isAttached(UInt16 remoteProcId)
393 {
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 }
406 }
408 /*
409 * ======== Ipc_detach ========
410 */
411 Int Ipc_detach(UInt16 remoteProcId)
412 {
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);
628 }
630 /*
631 * ======== Ipc_readConfig ========
632 */
633 Int Ipc_readConfig(UInt16 remoteProcId, UInt32 tag, Ptr cfg, SizeT size)
634 {
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);
684 }
686 /*
687 * ======== Ipc_start ========
688 */
689 Int Ipc_start()
690 {
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);
807 }
809 /*
810 * ======== Ipc_stop ========
811 */
812 Int Ipc_stop()
813 {
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);
846 }
848 /*
849 * ======== Ipc_writeConfig ========
850 */
851 Int Ipc_writeConfig(UInt16 remoteProcId, UInt32 tag, Ptr cfg, SizeT size)
852 {
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);
962 }
964 /*
965 *************************************************************************
966 * Module Functions
967 *************************************************************************
968 */
970 /*
971 * ======== ti_sdo_ipc_Ipc_dummy ========
972 */
973 Void ti_sdo_ipc_Ipc_dummy()
974 {
975 }
977 /*
978 * ======== ti_sdo_ipc_Ipc_getEntry ========
979 */
980 Void ti_sdo_ipc_Ipc_getEntry(ti_sdo_ipc_Ipc_Entry *entry)
981 {
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;
995 }
997 /*
998 * ======== ti_sdo_ipc_Ipc_setEntry ========
999 */
1000 Void ti_sdo_ipc_Ipc_setEntry(ti_sdo_ipc_Ipc_Entry *entry)
1001 {
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;
1011 }
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)
1023 {
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);
1045 }
1047 /*
1048 * ======== ti_sdo_ipc_Ipc_getRegion0ReservedSize ========
1049 */
1050 SizeT ti_sdo_ipc_Ipc_getRegion0ReservedSize(Void)
1051 {
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);
1058 }
1060 /*
1061 * ======== ti_sdo_ipc_Ipc_getSlaveAddr ========
1062 */
1063 Ptr ti_sdo_ipc_Ipc_getSlaveAddr(UInt16 remoteProcId, Ptr sharedAddr)
1064 {
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);
1086 }
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)
1100 {
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);
1180 }
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)
1189 {
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);
1246 }
1248 /*
1249 * ======== ti_sdo_ipc_Ipc_reservedSizePerProc ========
1250 */
1251 SizeT ti_sdo_ipc_Ipc_reservedSizePerProc(Void)
1252 {
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);
1268 }