/* * ======== GatePetersonN_Instance_init ======== */ Int GatePetersonN_Instance_init(GatePetersonN_Object *obj, IGateProvider_Handle localGate, const GatePetersonN_Params *params, Error_Block *eb) { SizeT offset; SizeT minAlign = Memory_getMaxDefaultTypeAlign(); SizeT i; if (SharedRegion_getCacheLineSize(params->regionId) > minAlign) { minAlign = SharedRegion_getCacheLineSize(params->regionId); } Assert_isTrue(params->sharedAddr != NULL, ti_sdo_ipc_Ipc_A_invParam); Assert_isTrue(GatePetersonN_numInstances != 0, ti_sdo_ipc_Ipc_A_invParam); obj->localGate = localGate; obj->cacheEnabled = SharedRegion_isCacheEnabled(params->regionId); obj->cacheLineSize = SharedRegion_getCacheLineSize(params->regionId); obj->nested = 0; /* This is not cluster aware: * obj->numProcessors = MultiProc_getNumProcessors(); * obj->selfId = MultiProc_self(); */ /* Cluster aware initialization */ obj->numProcessors = MultiProc_getNumProcsInCluster(); /* set selfId to 0-based offset within cluster. */ obj->selfId = MultiProc_self() - MultiProc_getBaseIdOfCluster(); /* Assign shared memory addresses for the protocol state variables */ offset = 0; for (i=0; i < obj->numProcessors; i++) { obj->enteredStage[i] = (Int32 *)((UArg)(params->sharedAddr) + offset); offset += minAlign; } for (i=0; i < obj->numProcessors - 1; i++) { obj->lastProcEnteringStage[i] = (Int32 *)((UArg)(params->sharedAddr) + offset); offset += minAlign; } if (!params->openFlag) { /* Creating. */ obj->objType = ti_sdo_ipc_Ipc_ObjType_CREATEDYNAMIC; GatePetersonN_postInit(obj); } else { /* Opening. */ obj->objType = ti_sdo_ipc_Ipc_ObjType_OPENDYNAMIC; } return (0); }
/* * ======== MultiProc_setBaseIdOfCluster ======== */ Int MultiProc_setBaseIdOfCluster(UInt16 id) { /* * Check the following * 1. Make sure the statically configured constant was invalid. * To call setBaseIdOfCluster, the id must have been set to invalid. * 2. Make sure the call is made before module startup */ if ((MultiProc_getBaseIdOfCluster() == MultiProc_INVALIDID) && (Startup_rtsDone() == FALSE)) { /* It is ok to set the id */ MultiProc_module->baseIdOfCluster = id; return (MultiProc_S_SUCCESS); } return (MultiProc_E_FAIL); }
/* * ======== Ipc_start ======== */ Int Ipc_start() { Int i; UInt16 baseId = MultiProc_getBaseIdOfCluster(); SharedRegion_Entry entry; Ptr ipcSharedAddr; Ptr gateMPSharedAddr; GateMP_Params gateMPParams; Int status; /* Check whether Ipc_start has been called. If so, succeed. */ if (Ipc_module->ipcSharedAddr != NULL) { return (Ipc_S_ALREADYSETUP); } if (ti_sdo_ipc_Ipc_generateSlaveDataForHost) { /* get Ipc_sr0MemorySetup out of the cache */ Cache_inv(&Ipc_sr0MemorySetup, sizeof(Ipc_sr0MemorySetup), Cache_Type_ALL, TRUE); /* check Ipc_sr0MemorySetup variable */ if (Ipc_sr0MemorySetup == 0x0) { return (Ipc_E_NOTREADY); } } /* get region 0 information */ SharedRegion_getEntry(0, &entry); /* if entry is not valid then return */ if (entry.isValid == FALSE) { return (Ipc_E_NOTREADY); } /* * Need to reserve memory in region 0 for processor synchronization. * This must done before SharedRegion_start(). */ ipcSharedAddr = ti_sdo_ipc_SharedRegion_reserveMemory( 0, Ipc_getRegion0ReservedSize()); /* must reserve memory for GateMP before SharedRegion_start() */ gateMPSharedAddr = ti_sdo_ipc_SharedRegion_reserveMemory(0, ti_sdo_ipc_GateMP_getRegion0ReservedSize()); /* Init params for default gate (must match those in GateMP_start()) */ GateMP_Params_init(&gateMPParams); gateMPParams.localProtect = GateMP_LocalProtect_TASKLET; if (ti_sdo_utils_MultiProc_numProcessors > 1) { gateMPParams.remoteProtect = GateMP_RemoteProtect_SYSTEM; } else { gateMPParams.remoteProtect = GateMP_RemoteProtect_NONE; } /* reserve memory for default gate before SharedRegion_start() */ ti_sdo_ipc_SharedRegion_reserveMemory(0, GateMP_sharedMemReq(&gateMPParams)); /* clear the reserved memory */ ti_sdo_ipc_SharedRegion_clearReservedMemory(); /* Set shared addresses */ Ipc_module->ipcSharedAddr = ipcSharedAddr; Ipc_module->gateMPSharedAddr = gateMPSharedAddr; /* create default GateMP, must be called before SharedRegion start */ status = ti_sdo_ipc_GateMP_start(Ipc_module->gateMPSharedAddr); if (status < 0) { return (status); } /* create HeapMemMP in each SharedRegion */ status = ti_sdo_ipc_SharedRegion_start(); if (status < 0) { return (status); } /* Call attach for all procs if procSync is ALL */ if (ti_sdo_ipc_Ipc_procSync == ti_sdo_ipc_Ipc_ProcSync_ALL) { /* Must attach to owner first to get default GateMP and HeapMemMP */ if (MultiProc_self() != entry.ownerProcId) { do { status = Ipc_attach(entry.ownerProcId); } while (status == Ipc_E_NOTREADY); if (status < 0) { /* Ipc_attach failed. Get out of Ipc_start */ return (status); } } /* Loop to attach to all other processors in cluster */ for (i = 0; i < ti_sdo_utils_MultiProc_numProcsInCluster; i++, baseId++) { if ((baseId == MultiProc_self()) || (baseId == entry.ownerProcId)) { continue; } /* Skip the processor if there are no interrupt lines to it */ if (Notify_numIntLines(baseId) == 0) { continue; } /* call Ipc_attach for every remote processor */ do { status = Ipc_attach(baseId); } while (status == Ipc_E_NOTREADY); if (status < 0) { /* Ipc_attach failed. Get out of Ipc_start */ return (status); } } } return (status); }
/* * ======== Ipc_detach ======== */ Int Ipc_detach(UInt16 remoteProcId) { Int i; UInt16 baseId = MultiProc_getBaseIdOfCluster(); UInt16 clusterId = ti_sdo_utils_MultiProc_getClusterId(remoteProcId); Ptr notifySharedAddr; Ptr nsrnSharedAddr; Ptr msgqSharedAddr; volatile ti_sdo_ipc_Ipc_Reserved *slave, *master; SharedRegion_Entry entry; ti_sdo_ipc_Ipc_ProcEntry *ipc; SizeT reservedSize = ti_sdo_ipc_Ipc_reservedSizePerProc(); Bool cacheEnabled = SharedRegion_isCacheEnabled(0); Int status = Ipc_S_SUCCESS; UInt hwiKey; /* Assert remoteProcId is in our cluster and isn't our own */ Assert_isTrue(clusterId < ti_sdo_utils_MultiProc_numProcsInCluster, ti_sdo_utils_MultiProc_A_invalidMultiProcId); Assert_isTrue(remoteProcId != MultiProc_self(), ti_sdo_ipc_Ipc_A_invArgument); /* for checking and incrementing attached below */ hwiKey = Hwi_disable(); if (Ipc_module->procEntry[clusterId].attached > 1) { /* only detach if attach count reaches 1 */ Ipc_module->procEntry[clusterId].attached--; Hwi_restore(hwiKey); return (Ipc_S_BUSY); } else if (Ipc_module->procEntry[clusterId].attached == 0) { /* already detached, restore interrupts and return success */ Hwi_restore(hwiKey); return (Ipc_S_SUCCESS); } /* restore interrupts */ Hwi_restore(hwiKey); /* get region 0 information */ SharedRegion_getEntry(0, &entry); /* * Make sure we detach from all other procs in cluster before * detaching from owner of SR 0. */ if (remoteProcId == entry.ownerProcId) { for (i = 0; i < ti_sdo_utils_MultiProc_numProcsInCluster; i++, baseId++) { if ((baseId != MultiProc_self()) && (baseId != entry.ownerProcId) && (Ipc_module->procEntry[i].attached)) { return (Ipc_E_FAIL); } } } /* get the paramters associated with remoteProcId */ ipc = &(Ipc_module->procEntry[clusterId]); /* determine the slave's slot */ slave = Ipc_getSlaveAddr(remoteProcId, Ipc_module->ipcSharedAddr); /* determine the master's slot */ master = ti_sdo_ipc_Ipc_getMasterAddr(remoteProcId, Ipc_module->ipcSharedAddr); if (cacheEnabled) { Cache_inv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE); Cache_inv((Ptr)master, reservedSize, Cache_Type_ALL, TRUE); } if (MultiProc_self() < remoteProcId) { /* check to make sure master is not trying to attach */ if (master->startedKey == ti_sdo_ipc_Ipc_PROCSYNCSTART) { return (Ipc_E_NOTREADY); } } else { /* check to make sure slave is not trying to attach */ if (slave->startedKey == ti_sdo_ipc_Ipc_PROCSYNCSTART) { return (Ipc_E_NOTREADY); } } /* The slave processor waits for master to finish its detach sequence */ if (MultiProc_self() < remoteProcId) { if (master->startedKey != ti_sdo_ipc_Ipc_PROCSYNCDETACH) { return (Ipc_E_NOTREADY); } } /* Call user detach fxns */ for (i = 0; i < ti_sdo_ipc_Ipc_numUserFxns; i++) { if (ti_sdo_ipc_Ipc_userFxns[i].userFxn.detach) { status = ti_sdo_ipc_Ipc_userFxns[i].userFxn.detach( ti_sdo_ipc_Ipc_userFxns[i].arg, remoteProcId); if (status < 0) { return (status); } } } if ((ipc->entry.setupMessageQ) && (ti_sdo_ipc_MessageQ_SetupTransportProxy_isRegistered(remoteProcId))) { /* call MessageQ_detach for remote processor */ status = ti_sdo_ipc_MessageQ_SetupTransportProxy_detach(remoteProcId); if (status < 0) { return (Ipc_E_FAIL); } if (slave->transportSRPtr) { /* free the memory if slave processor */ if (MultiProc_self() < remoteProcId) { /* get the pointer to MessageQ transport instance */ msgqSharedAddr = SharedRegion_getPtr(slave->transportSRPtr); /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), msgqSharedAddr, ti_sdo_ipc_MessageQ_SetupTransportProxy_sharedMemReq( msgqSharedAddr)); /* set pointer for MessageQ transport instance back to NULL */ slave->transportSRPtr = NULL; } } } if ((ipc->entry.setupNotify) && (ti_sdo_utils_NameServer_isRegistered(remoteProcId))) { /* call NameServer_SetupProxy_detach for remote processor */ status = ti_sdo_utils_NameServer_SetupProxy_detach(remoteProcId); if (status < 0) { return (Ipc_E_FAIL); } if (slave->nsrnSRPtr) { /* free the memory if slave processor */ if (MultiProc_self() < remoteProcId) { /* get the pointer to NSRN instance */ nsrnSharedAddr = SharedRegion_getPtr(slave->nsrnSRPtr); /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), nsrnSharedAddr, ti_sdo_utils_NameServer_SetupProxy_sharedMemReq( nsrnSharedAddr)); /* set pointer for NSRN instance back to NULL */ slave->nsrnSRPtr = NULL; } } } if ((ipc->entry.setupNotify) && (Notify_intLineRegistered(remoteProcId, 0))) { /* call Notify_detach for remote processor */ status = ti_sdo_ipc_Notify_detach(remoteProcId); if (status < 0) { return (Ipc_E_FAIL); } if (slave->notifySRPtr) { /* free the memory if slave processor */ if (MultiProc_self() < remoteProcId) { /* get the pointer to Notify instance */ notifySharedAddr = SharedRegion_getPtr(slave->notifySRPtr); /* free the memory back to SharedRegion 0 heap */ Memory_free(SharedRegion_getHeap(0), notifySharedAddr, Notify_sharedMemReq(remoteProcId, notifySharedAddr)); /* set pointer for Notify instance back to NULL */ slave->notifySRPtr = NULL; } } } /* close any HeapMemMP which may have been opened */ status = ti_sdo_ipc_SharedRegion_detach(remoteProcId); if (status < 0) { return (status); } /* close any GateMP which may have been opened */ status = ti_sdo_ipc_GateMP_detach(remoteProcId); if (status < 0) { return (status); } if (MultiProc_self() < remoteProcId) { slave->configListHead = ti_sdo_ipc_SharedRegion_INVALIDSRPTR; slave->startedKey = ti_sdo_ipc_Ipc_PROCSYNCDETACH; if (cacheEnabled) { Cache_wbInv((Ptr)slave, reservedSize, Cache_Type_ALL, TRUE); } } else { master->configListHead = ti_sdo_ipc_SharedRegion_INVALIDSRPTR; master->startedKey = ti_sdo_ipc_Ipc_PROCSYNCDETACH; if (cacheEnabled) { Cache_wbInv((Ptr)master, reservedSize, Cache_Type_ALL, TRUE); } } /* attached must be decremented atomically */ hwiKey = Hwi_disable(); /* now detached from remote processor */ Ipc_module->procEntry[clusterId].attached--; /* restore interrupts */ Hwi_restore(hwiKey); return (status); }
int main (int argc, char ** argv) { Int status = 0; int opt; UInt numLoops = NUM_LOOPS_DFLT; UInt16 procId = PROC_ID_DFLT; UInt32 faultId = 0; while ((opt = getopt(argc, argv, "f:")) != -1) { switch (opt) { case 'f': /* * Argument for -f corresponds to remote-side "fault" commands. * Negative commands cause remote fault before remote MessageQ_put. * Positive commands cause remote fault after remote MessageQ_put. */ faultId = atoi(optarg); printf("fault %d will be sent in 1st msg\n", faultId); break; default: fprintf(stderr, "Unknown arg '%s'\n", optarg); return 1; } } /* Parse Args: */ switch (argc - optind + 1) { case 1: /* use defaults */ break; case 2: numLoops = atoi(argv[optind]); break; case 3: numLoops = atoi(argv[optind]); procId = atoi(argv[optind + 1]); break; default: printf("Usage: %s [<numLoops>] [<ProcId>]\n", argv[0]); printf("\tDefaults: numLoops: %d; ProcId: %d\n", NUM_LOOPS_DFLT, PROC_ID_DFLT); exit(0); } /* configure the transport factory */ Ipc_transportConfig(&TransportRpmsg_Factory); /* IPC initialization */ status = Ipc_start(); if (status < 0) { printf("Error: Ipc_start failed, error=%d\n", status); goto exit; } if ((procId == 0) || (procId >= (MultiProc_getBaseIdOfCluster() + MultiProc_getNumProcessors()))) { printf("ProcId (%d) must be nonzero and less than %d\n", procId, MultiProc_getBaseIdOfCluster() + MultiProc_getNumProcessors()); Ipc_stop(); exit(0); } printf("Using numLoops: %d; procId : %d\n", numLoops, procId); if (MessageQApp_execute(numLoops, procId, faultId) < 0) { int nAttachAttempts = 1; printf("MessageQApp_execute failed, attempting detach/attach...\n"); Ipc_detach(procId); while (Ipc_attach(procId) != Ipc_S_SUCCESS) { nAttachAttempts++; if ((nAttachAttempts % 1000) == 0) { printf("Ipc_attach(%d) failed\n", procId); } } printf("Ipc_attach(%d) succeeded (after %d tries)\n", procId, nAttachAttempts); /* call without fault this time */ MessageQApp_execute(numLoops, procId, 0); } Ipc_stop(); exit: return (status); }