void* CkCopyMsg(void **pMsg) {// cannot simply memcpy, because srcMsg could be varsize msg register void *srcMsg = *pMsg; register envelope *env = UsrToEnv(srcMsg); register unsigned char msgidx = env->getMsgIdx(); if(!env->isPacked() && _msgTable[msgidx]->pack) { srcMsg = _msgTable[msgidx]->pack(srcMsg); UsrToEnv(srcMsg)->setPacked(1); } register int size = UsrToEnv(srcMsg)->getTotalsize(); register envelope *newenv = (envelope *) CmiAlloc(size); CmiMemcpy(newenv, UsrToEnv(srcMsg), size); //memcpy(newenv, UsrToEnv(srcMsg), size); if(UsrToEnv(srcMsg)->isPacked() && _msgTable[msgidx]->unpack) { srcMsg = _msgTable[msgidx]->unpack(srcMsg); UsrToEnv(srcMsg)->setPacked(0); } *pMsg = srcMsg; if(newenv->isPacked() && _msgTable[msgidx]->unpack) { srcMsg = _msgTable[msgidx]->unpack(EnvToUsr(newenv)); UsrToEnv(srcMsg)->setPacked(0); } else srcMsg = EnvToUsr(newenv); setMemoryTypeMessage(newenv); return srcMsg; }
void pupSingleMessage(PUP::er &p, int curObj, void *msg) { beginItem(p,curObj); int isCharm=0; const char *type="Converse"; p.comment("name"); char name[128]; if (msg == (void*)-1) { type="Sentinel"; p((char*)type, strlen(type)); return; } #if ! CMK_BIGSIM_CHARM if (CmiGetHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Local Charm";} if (CmiGetXHandler(msg)==_charmHandlerIdx) {isCharm=1; type="Network Charm";} #else isCharm=1; type="BG"; #endif if (curObj < 0) type="Conditional"; sprintf(name,"%s %d: %s (%d)","Message",curObj,type,CmiGetHandler(msg)); p(name, strlen(name)); if (isCharm) { /* charm message */ p.comment("charmMsg"); p.synchronize(PUP::sync_begin_object); envelope *env=(envelope *)msg; CkUnpackMessage(&env); //messages[curObj]=env; CpdPupMessage(p, EnvToUsr(env)); //CkPupMessage(p, &messages[curObj], 0); p.synchronize(PUP::sync_end_object); } }
void RectMulticastStrategy::handleMessageForward(void *msg){ envelope *env = (envelope *)msg; RECORD_RECV_STATS(getInstance(), env->getTotalsize(), env->getSrcPe()); //Section multicast base message CkMcastBaseMsg *cbmsg = (CkMcastBaseMsg *)EnvToUsr(env); int status = cbmsg->_cookie.sInfo.cInfo.status; ComlibPrintf("[%d] In handleMessageForward %d\n", CkMyPe(), status); if(status == COMLIB_MULTICAST_NEW_SECTION) handleNewMulticastMessage(env); else { //status == COMLIB_MULTICAST_OLD_SECTION, use the cached section id ComlibSectionHashKey key(cbmsg->_cookie.pe, cbmsg->_cookie.sInfo.cInfo.id); ComlibRectSectionHashObject *obj; obj = sec_ht.get(key); if(obj == NULL) CkAbort("Destination indices is NULL\n"); #ifndef LOCAL_MULTI_OFF localMulticast(env, obj); #endif remoteMulticast(env, obj); } }
// For source not in rectangle case, forward to corner of rectangle // void RectMulticastStrategy::forwardMulticast(envelope *env, ComlibRectSectionHashObject *obj) { ComlibPrintf("[%d] forwardMulticast \n", CkMyPe()); int *pelist = obj->pelist; int npes = obj->npes; if(npes == 0) { CmiFree(env); return; } // handler is changed to special root handler CmiSetHandler(env, handlerId); ((CmiMsgHeaderExt *) env)->stratid = getInstance(); //Collect Multicast Statistics RECORD_SENDM_STATS(getInstance(), env->getTotalsize(), pelist, npes); CkPackMessage(&env); //Sending a remote multicast ComlibMulticastMsg *cbmsg = (ComlibMulticastMsg *)EnvToUsr(env); int sectionID=cbmsg->_cookie.sInfo.cInfo.id; // CmiSyncListSendAndFree(npes, pelist, env->getTotalsize(), (char*)env); CmiSyncSendAndFree(obj->cornerRoot, env->getTotalsize(), (char*)env); //CmiSyncBroadcastAndFree(env->getTotalsize(), (char*)env); }
static inline void _processRODataMsg(envelope *env) { //Unpack each readonly: if(!CmiMyRank()) { PUP::fromMem pu((char *)EnvToUsr(env)); for(size_t i=0;i<_readonlyTable.size();i++) { _readonlyTable[i]->pupData(pu); } } CmiFree(env); }
void ComlibSectionInfo::getPeList(envelope *cb_env, int npes, int *&pelist) { ComlibMulticastMsg *ccmsg = (ComlibMulticastMsg *)EnvToUsr(cb_env); int i; CkAssert(npes==ccmsg->nPes); for (i=0; i<ccmsg->nPes; ++i) { pelist[i]=ccmsg->indicesCount[i].pe; } }
void* CkAllocMsg(int msgIdx, int msgBytes, int prioBits) { register envelope* env; env = _allocEnv(ForChareMsg, msgBytes, prioBits); setMemoryTypeMessage(env); env->setQueueing(_defaultQueueing); env->setMsgIdx(msgIdx); return EnvToUsr(env); }
// converse handler // send converse message to avoid QD detection static void migrationDone(envelope *env, CkCoreState *ck) { // Since migrationsDone will deal with Charm++ messages, // the LB must obey the CkMessageWatcher orders. if (ck->watcher!=NULL) { if (!ck->watcher->processMessage(&env,ck)) return; } NullLB *lb = (NullLB*)CkLocalBranch(_theNullLB); lb->migrationsDone(); CkFreeSysMsg(EnvToUsr(env)); }
void forwardMsg(int ep,const CkArrayIndex &idx, const CkArrayID &a, int nBytes,char *env) { ckout<<"DelegateMgr> Recv message for "<<idx.data()[0]<<endl; //Have to allocate a new message because of Charm++'s // weird allocate rules: envelope *msg=(envelope *)CmiAlloc(nBytes); memcpy(msg,env,nBytes); CkUnpackMessage(&msg); CProxy_CkArray ap(msg->getsetArrayMgr()); ap.ckLocalBranch()->deliver((CkMessage *)EnvToUsr(msg),CkDeliver_inline); }
void ComlibSectionInfo::unpack(envelope *cb_env, int &nLocalElems, CkArrayIndex *&dest_indices, envelope *&env) { ComlibMulticastMsg *ccmsg = (ComlibMulticastMsg *)EnvToUsr(cb_env); int i; dest_indices = ccmsg->indices; for (i=0; i<ccmsg->nPes; ++i) { if (ccmsg->indicesCount[i].pe == CkMyPe()) break; dest_indices += ccmsg->indicesCount[i].count; } if(i >= ccmsg->nPes) { //cheap hack for rect bcast nLocalElems=0; dest_indices=NULL; } else { nLocalElems = ccmsg->indicesCount[i].count; /* ComlibPrintf("Unpacking: %d local elements:",nLocalElems); for (int j=0; j<nLocalElems; ++j) ComlibPrintf(" %d",((int*)&dest_indices[j])[1]); ComlibPrintf("\n"); */ /* for(int count = 0; count < ccmsg->nIndices; count++){ CkArrayIndex idx = ccmsg->indices[count]; //This will work because. lastknown always knows if I have the //element of not int dest_proc = ComlibGetLastKnown(destArrayID, idx); //CkArrayID::CkLocalBranch(destArrayID)->lastKnown(idx); // if(dest_proc == CkMyPe()) dest_indices.insertAtEnd(idx); } */ } envelope *usrenv = (envelope *) ccmsg->usrMsg; env = (envelope *)CmiAlloc(usrenv->getTotalsize()); memcpy(env, usrenv, usrenv->getTotalsize()); #if CMK_REPLAYSYSTEM || CMK_TRACE_ENABLED env->setEvent(cb_env->getEvent()); #endif }
virtual void pup(PUP::er &p, CpdListItemsRequest &req) { envelope *env = (envelope*)(((unsigned int)req.lo) + (((unsigned long)req.hi)<<32)+sizeof(CmiChunkHeader)); beginItem(p, 0); const char *type="Converse"; p.comment("name"); char name[128]; if (CmiGetHandler(env)==_charmHandlerIdx) {type="Local Charm";} if (CmiGetXHandler(env)==_charmHandlerIdx) {type="Network Charm";} sprintf(name,"%s 0: %s (%d)","Message",type,CmiGetHandler(env)); p(name, strlen(name)); p.comment("charmMsg"); p.synchronize(PUP::sync_begin_object); CpdPupMessage(p, EnvToUsr(env)); p.synchronize(PUP::sync_end_object); }
static void bdcastRO(void){ int i; //Determine the size of the RODataMessage PUP::sizer ps; for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps); //Allocate and fill out the RODataMessage envelope *env = _allocEnv(RODataMsg, ps.size()); PUP::toMem pp((char *)EnvToUsr(env)); for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp); env->setCount(++_numInitMsgs); env->setSrcPe(CkMyPe()); CmiSetHandler(env, _roRestartHandlerIdx); CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env); }
void* CkAllocBuffer(void *msg, int bufsize) { bufsize = CkMsgAlignLength(bufsize); register envelope *env = UsrToEnv(msg); register envelope *packbuf; packbuf = _allocEnv(env->getMsgtype(), bufsize, env->getPriobits()); register int size = packbuf->getTotalsize(); CmiMemcpy(packbuf, env, sizeof(envelope)); packbuf->setTotalsize(size); packbuf->setPacked(!env->isPacked()); CmiMemcpy(packbuf->getPrioPtr(), env->getPrioPtr(), packbuf->getPrioBytes()); return EnvToUsr(packbuf);; }
//Send the multicast message the local array elements. The message is //copied and sent if elements exist. void RectMulticastStrategy::localMulticast(envelope *env, ComlibRectSectionHashObject *obj) { int nIndices = obj->indices.size(); if(obj->msg != NULL) { CmiFree(obj->msg); obj->msg = NULL; } if(nIndices > 0) { void *msg = EnvToUsr(env); void *msg1 = msg; msg1 = CkCopyMsg(&msg); ComlibArrayInfo::localMulticast(&(obj->indices), UsrToEnv(msg1)); } }
void PipeBroadcastStrategy::deliver(char *msg, int dim) { envelope *env = (envelope*)msg; ComlibPrintf("[%d] PipeBroadcastStrategy::deliver\n",CkMyPe()); CkUnpackMessage(&env); //ComlibPrintf("isArray = %d\n", (getType() == ARRAY_STRATEGY)); if (getType() == ARRAY_STRATEGY) { // deliver the message to the predefined group "ainfo" ainfo.localBroadcast(env); } if (getType() == GROUP_STRATEGY) { // deliver the message to the predifined group "ginfo" //CkGroupID gid; //ginfo.getSourceGroup(gid); CkSendMsgBranchInline(env->getEpIdx(), EnvToUsr(env), CkMyPe(), env->getGroupNum()); } }
virtual void pup(PUP::er &p, CpdListItemsRequest &req) { int length; void ** messages; int curObj=0; void *msg; length = CdsFifo_Length((CdsFifo)(CpvAccess(conditionalQueue))); messages = CdsFifo_Enumerate(CpvAccess(conditionalQueue)); for (curObj=-length; curObj<0; curObj++) { void *msg = messages[length+curObj]; pupSingleMessage(p, curObj-1, msg); } delete[] messages; curObj = 0; length = CdsFifo_Length((CdsFifo)(CkpvAccess(debugQueue))); messages = CdsFifo_Enumerate(CkpvAccess(debugQueue)); if (CkpvAccess(lastBreakPointMsg) != NULL) { beginItem(p, -1); envelope *env=(envelope *)UsrToEnv(CkpvAccess(lastBreakPointMsg)); p.comment("name"); char *type=(char*)"Breakpoint"; p(type,strlen(type)); p.comment("charmMsg"); p.synchronize(PUP::sync_begin_object); CkUnpackMessage(&env); CpdPupMessage(p, EnvToUsr(env)); p.synchronize(PUP::sync_end_object); } for(curObj=req.lo; curObj<req.hi; curObj++) if ((curObj>=0) && (curObj<length)) { void *msg=messages[curObj]; /* converse message */ pupSingleMessage(p, curObj, msg); } delete[] messages; }
//Calls default multicast scheme to send the messages. It could //also call a converse lower level strategy to do the muiticast. //For example pipelined multicast void RectMulticastStrategy::remoteMulticast(envelope *env, ComlibRectSectionHashObject *obj) { ComlibPrintf("[%d] remoteMulticast \n", CkMyPe()); int npes = obj->npes; int *pelist = obj->pelist; // if(npes == 0) { // CmiFree(env); // return; // } //CmiSetHandler(env, handlerId); CmiSetHandler(env, CkpvAccess(strategy_handlerid)); ((CmiMsgHeaderExt *) env)->stratid = getInstance(); //Collect Multicast Statistics RECORD_SENDM_STATS(getInstance(), env->getTotalsize(), pelist, npes); int srcpe=env->getSrcPe(); CkPackMessage(&env); // int destid=env->getGroupNum().idx; //Sending a remote multicast ComlibMulticastMsg *cbmsg = (ComlibMulticastMsg *)EnvToUsr(env); int sectionID=cbmsg->_cookie.sInfo.cInfo.id; CkArrayID destid=obj->aid; // bgl_machineRectBcast should only be called once globally // per multicast int comm=computeKey(sectionID, srcpe, destid); ComlibPrintf("[%d] rectbcast using comm %d section %d srcpe %d request %p\n",CkMyPe(), comm, sectionID, srcpe, CkpvAccess(com_rect_ptr)->get(comm)); #ifdef COMLIB_RECT_DEBUG isSane(CkpvAccess(com_rect_ptr)->get(comm),comm); #endif bgl_machine_RectBcast(comm , (char*)env, env->getTotalsize()); //CmiSyncListSendAndFree(npes, pelist, env->getTotalsize(), (char*)env); //CmiSyncBroadcastAndFree(env->getTotalsize(), (char*)env); }
/** Create a new multicast message based upon the section info stored inside cmsg. */ ComlibMulticastMsg * ComlibSectionInfo::getNewMulticastMessage(CharmMessageHolder *cmsg, int needSort, int instanceID){ // cmsg->checkme(); if(cmsg->sec_id == NULL || cmsg->sec_id->_nElems == 0) return NULL; void *m = cmsg->getCharmMessage(); envelope *env = UsrToEnv(m); // Crate a unique identifier for section id in cmsg->sec_id initSectionID(cmsg->sec_id); CkPackMessage(&env); const CkArrayID destArrayID(env->getArrayMgr()); int nRemotePes=-1, nRemoteIndices=-1; ComlibMulticastIndexCount *indicesCount; int *belongingList; // Determine the last known locations of all the destination objects. getPeCount(cmsg->sec_id->_nElems, cmsg->sec_id->_elems, destArrayID, nRemotePes, nRemoteIndices, indicesCount, belongingList); // if (nRemotePes == 0) return NULL; #if 0 CkPrintf("nRemotePes=%d\n", nRemotePes); CkPrintf("nRemoteIndices=%d\n",nRemoteIndices); CkPrintf("env->getTotalsize()=%d\n", env->getTotalsize()); CkPrintf("cmsg->sec_id->_nElems=%d\n", cmsg->sec_id->_nElems); #endif int sizes[3]; sizes[0] = nRemotePes; sizes[1] = nRemoteIndices; // only those remote ///cmsg->sec_id->_nElems; sizes[2] = env->getTotalsize(); ComlibPrintf("Creating new comlib multicast message %d, %d %d\n", sizes[0], sizes[1], sizes[2]); ComlibMulticastMsg *msg = new(sizes, 0) ComlibMulticastMsg; msg->nPes = nRemotePes; msg->_cookie.info.sInfo.cInfo.instId = instanceID; msg->_cookie.info.sInfo.cInfo.id = MaxSectionID - 1; msg->_cookie.info.sInfo.cInfo.status = COMLIB_MULTICAST_NEW_SECTION; msg->_cookie.get_type() = COMLIB_MULTICAST_MESSAGE; msg->_cookie.get_pe() = CkMyPe(); // fill in the three pointers of the ComlibMulticastMsg memcpy(msg->indicesCount, indicesCount, sizes[0] * sizeof(ComlibMulticastIndexCount)); //memcpy(msg->indices, cmsg->sec_id->_elems, sizes[1] * sizeof(CkArrayIndex)); CkArrayIndex **indicesPe = (CkArrayIndex**)alloca(nRemotePes * sizeof(CkArrayIndex*)); if (needSort) { // if we are sorting the array, then we need to fix the problem that belongingList // refers to the original ordering! This is done by mapping indicesPe in a way coherent // with the original ordering. int previous, i, j; qsort(msg->indicesCount, sizes[0], sizeof(ComlibMulticastIndexCount), indexCountCompare); for (j=0; j<nRemotePes; ++j) if (indicesCount[j].pe == msg->indicesCount[0].pe) break; indicesPe[j] = msg->indices; previous = j; for (i=1; i<nRemotePes; ++i) { for (j=0; j<nRemotePes; ++j) if (indicesCount[j].pe == msg->indicesCount[i].pe) break; indicesPe[j] = indicesPe[previous] + indicesCount[previous].count; previous = j; } } else { indicesPe[0] = msg->indices; for (int i=1; i<nRemotePes; ++i) indicesPe[i] = indicesPe[i-1] + indicesCount[i-1].count; } for (int i=0; i<cmsg->sec_id->_nElems; ++i) { if (belongingList[i] >= 0) { // If the object is located on a remote PE (-1 is local) *indicesPe[belongingList[i]] = cmsg->sec_id->_elems[i]; indicesPe[belongingList[i]]++; } } memcpy(msg->usrMsg, env, sizes[2] * sizeof(char)); envelope *newenv = UsrToEnv(msg); delete [] indicesCount; delete [] belongingList; newenv->getArrayMgr() = env->getArrayMgr(); newenv->getsetArraySrcPe() = env->getsetArraySrcPe(); newenv->getsetArrayEp() = env->getsetArrayEp(); newenv->getsetArrayHops() = env->getsetArrayHops(); newenv->getsetArrayIndex() = env->getsetArrayIndex(); #if CMK_REPLAYSYSTEM || CMK_TRACE_ENABLED newenv->setEvent(env->getEvent()); #endif newenv->setSrcPe(env->getSrcPe()); return (ComlibMulticastMsg *)EnvToUsr(newenv); }
void RectMulticastStrategy::handleNewMulticastMessage(envelope *env) { ComlibPrintf("[%d] : In handleNewMulticastMessage\n", CkMyPe()); CkUnpackMessage(&env); int sender=env->getSrcPe(); int localElems; envelope *newenv; CkArrayIndex *local_idx_list; sinfo.unpack(env, localElems, local_idx_list, newenv); ComlibMulticastMsg *cbmsg = (ComlibMulticastMsg *)EnvToUsr(env); ComlibSectionHashKey key(cbmsg->_cookie.pe, cbmsg->_cookie.sInfo.cInfo.id); ComlibRectSectionHashObject *old_obj = NULL; old_obj = sec_ht.get(key); if(old_obj != NULL) { delete old_obj; } /* CkArrayIndex *idx_list_array = new CkArrayIndex[idx_list.size()]; for(int count = 0; count < idx_list.size(); count++) idx_list_array[count] = idx_list[count]; */ int cur_sec_id=cbmsg->_cookie.sInfo.cInfo.id; // need everyPe for rectangle not just local_idx_list ComlibMulticastMsg *lll = cbmsg; envelope *ppp = UsrToEnv(cbmsg); CkUnpackMessage(&ppp); int ttt=0; int uuu=0; for (int i=0; i<lll->nPes; ++i) { // ComlibPrintf(" %d (",lll->indicesCount[i].pe); uuu++; for (int j=0; j<lll->indicesCount[i].count; ++j) { // ComlibPrintf(" %d",((int*)&(lll->indices[ttt]))[1]); ttt++; } // ComlibPrintf(" )"); } ComlibPrintf("[%d] cbmsg for intermediate has %d indices %d pes\n",CkMyPe(),ttt, uuu); CkAssert(uuu>0); CkAssert(ttt>0); ComlibRectSectionHashObject *new_obj = createObjectOnIntermediatePe(ttt, cbmsg->indices, cbmsg->nPes, cbmsg->indicesCount, sender, cur_sec_id ); // now revise obj for local use only sinfo.getRemotePelist(localElems, local_idx_list, new_obj->npes, new_obj->pelist); sinfo.getLocalIndices(localElems, local_idx_list, new_obj->indices); sec_ht.put(key) = new_obj; CkPackMessage(&newenv); #ifndef LOCAL_MULTI_OFF localMulticast(newenv, new_obj); //local multicast always copies #endif CmiFree(newenv); //NEED this }
/** This is the main charm setup routine. It's called on all processors after Converse initialization. This routine gets passed to Converse from "main.C". The main purpose of this routine is to set up the objects and Ckpv's used during a regular Charm run. See the comment at the top of the file for overall flow. */ void _initCharm(int unused_argc, char **argv) { int inCommThread = (CmiMyRank() == CmiMyNodeSize()); DEBUGF(("[%d,%.6lf ] _initCharm started\n",CmiMyPe(),CmiWallTimer())); CkpvInitialize(size_t *, _offsets); CkpvAccess(_offsets) = new size_t[32]; CkpvInitialize(PtrQ*,_buffQ); CkpvInitialize(PtrVec*,_bocInitVec); CkpvInitialize(void*, _currentChare); CkpvInitialize(int, _currentChareType); CkpvInitialize(CkGroupID, _currentGroup); CkpvInitialize(void *, _currentNodeGroupObj); CkpvInitialize(CkGroupID, _currentGroupRednMgr); CkpvInitialize(GroupTable*, _groupTable); CkpvInitialize(GroupIDTable*, _groupIDTable); CkpvInitialize(CmiImmediateLockType, _groupTableImmLock); CkpvInitialize(bool, _destroyingNodeGroup); CkpvAccess(_destroyingNodeGroup) = false; CkpvInitialize(UInt, _numGroups); CkpvInitialize(int, _numInitsRecd); CkpvInitialize(int, _initdone); CkpvInitialize(char**, Ck_argv); CkpvAccess(Ck_argv)=argv; CkpvInitialize(MsgPool*, _msgPool); CkpvInitialize(CkCoreState *, _coreState); /* Added for evacuation-sayantan */ #ifndef __BIGSIM__ CpvInitialize(char *,_validProcessors); #endif CkpvInitialize(char ,startedEvac); CpvInitialize(int,serializer); _initChareTables(); // for checkpointable plain chares CksvInitialize(UInt, _numNodeGroups); CksvInitialize(GroupTable*, _nodeGroupTable); CksvInitialize(GroupIDTable, _nodeGroupIDTable); CksvInitialize(CmiImmediateLockType, _nodeGroupTableImmLock); CksvInitialize(CmiNodeLock, _nodeLock); CksvInitialize(PtrVec*,_nodeBocInitVec); CksvInitialize(UInt,_numInitNodeMsgs); CkpvInitialize(int,_charmEpoch); CkpvAccess(_charmEpoch)=0; CksvInitialize(int, _triggersSent); CksvAccess(_triggersSent) = 0; CkpvInitialize(_CkOutStream*, _ckout); CkpvInitialize(_CkErrStream*, _ckerr); CkpvInitialize(Stats*, _myStats); CkpvAccess(_groupIDTable) = new GroupIDTable(0); CkpvAccess(_groupTable) = new GroupTable; CkpvAccess(_groupTable)->init(); CkpvAccess(_groupTableImmLock) = CmiCreateImmediateLock(); CkpvAccess(_numGroups) = 1; // make 0 an invalid group number CkpvAccess(_buffQ) = new PtrQ(); CkpvAccess(_bocInitVec) = new PtrVec(); CkpvAccess(_currentNodeGroupObj) = NULL; if(CkMyRank()==0) { CksvAccess(_numNodeGroups) = 1; //make 0 an invalid group number CksvAccess(_numInitNodeMsgs) = 0; CksvAccess(_nodeLock) = CmiCreateLock(); CksvAccess(_nodeGroupTable) = new GroupTable(); CksvAccess(_nodeGroupTable)->init(); CksvAccess(_nodeGroupTableImmLock) = CmiCreateImmediateLock(); CksvAccess(_nodeBocInitVec) = new PtrVec(); } CkCallbackInit(); CmiNodeAllBarrier(); #if ! CMK_BIGSIM_CHARM initQd(argv); // bigsim calls it in ConverseCommonInit #endif CkpvAccess(_coreState)=new CkCoreState(); CkpvAccess(_numInitsRecd) = 0; CkpvAccess(_initdone) = 0; CkpvAccess(_ckout) = new _CkOutStream(); CkpvAccess(_ckerr) = new _CkErrStream(); _charmHandlerIdx = CkRegisterHandler((CmiHandler)_bufferHandler); _initHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler); CkNumberHandlerEx(_initHandlerIdx, (CmiHandlerEx)_initHandler, CkpvAccess(_coreState)); _roRestartHandlerIdx = CkRegisterHandler((CmiHandler)_roRestartHandler); _exitHandlerIdx = CkRegisterHandler((CmiHandler)_exitHandler); //added for interoperabilitY _libExitHandlerIdx = CkRegisterHandler((CmiHandler)_libExitHandler); _bocHandlerIdx = CkRegisterHandler((CmiHandler)_initHandler); CkNumberHandlerEx(_bocHandlerIdx, (CmiHandlerEx)_initHandler, CkpvAccess(_coreState)); #ifdef __BIGSIM__ if(BgNodeRank()==0) #endif _infoIdx = CldRegisterInfoFn((CldInfoFn)_infoFn); _triggerHandlerIdx = CkRegisterHandler((CmiHandler)_triggerHandler); _ckModuleInit(); CldRegisterEstimator((CldEstimator)_charmLoadEstimator); _futuresModuleInit(); // part of futures implementation is a converse module _loadbalancerInit(); _metabalancerInit(); #if CMK_MEM_CHECKPOINT init_memcheckpt(argv); #endif initCharmProjections(); #if CMK_TRACE_IN_CHARM // initialize trace module in ck traceCharmInit(argv); #endif CkpvInitialize(int, envelopeEventID); CkpvAccess(envelopeEventID) = 0; CkMessageWatcherInit(argv,CkpvAccess(_coreState)); /** The rank-0 processor of each node calls the translator-generated "_register" routines. _register routines call the charm.h "CkRegister*" routines, which record function pointers and class information for all Charm entities, like Chares, Arrays, and readonlies. There's one _register routine generated for each .ci file. _register routines *must* be called in the same order on every node, and *must not* be called by multiple threads simultaniously. */ #ifdef __BIGSIM__ if(BgNodeRank()==0) #else if(CkMyRank()==0) #endif { SDAG::registerPUPables(); CmiArgGroup("Charm++",NULL); _parseCommandLineOpts(argv); _registerInit(); CkRegisterMsg("System", 0, 0, CkFreeMsg, sizeof(int)); CkRegisterChareInCharm(CkRegisterChare("null", 0, TypeChare)); CkIndex_Chare::__idx=CkRegisterChare("Chare", sizeof(Chare), TypeChare); CkRegisterChareInCharm(CkIndex_Chare::__idx); CkIndex_Group::__idx=CkRegisterChare("Group", sizeof(Group), TypeGroup); CkRegisterChareInCharm(CkIndex_Group::__idx); CkRegisterEp("null", (CkCallFnPtr)_nullFn, 0, 0, 0+CK_EP_INTRINSIC); /** These _register calls are for the built-in Charm .ci files, like arrays and load balancing. If you add a .ci file to charm, you'll have to add a call to the _register routine here, or make your library into a "-module". */ _registerCkFutures(); _registerCkArray(); _registerLBDatabase(); _registerMetaBalancer(); _registerCkCallback(); _registertempo(); _registerwaitqd(); _registerCkCheckpoint(); #if CMK_MEM_CHECKPOINT _registerCkMemCheckpoint(); #endif /* Setup Control Point Automatic Tuning Framework. By default it is enabled as a part of charm, however it won't enable its tracing module unless a +CPEnableMeasurements command line argument is specified. See trace-common.C for more info Thus there should be no noticable overhead to always having the control point framework linked in. */ #if CMK_WITH_CONTROLPOINT _registerPathHistory(); _registerControlPoints(); _registerTraceControlPoints(); #endif /** CkRegisterMainModule is generated by the (unique) "mainmodule" .ci file. It will include calls to register all the .ci files. */ CkRegisterMainModule(); /** _registerExternalModules is actually generated by charmc at link time (as "moduleinit<pid>.C"). This generated routine calls the _register functions for the .ci files of libraries linked using "-module". This funny initialization is most useful for AMPI/FEM programs, which don't have a .ci file and hence have no other way to control the _register process. */ _registerExternalModules(argv); _registerDone(); } /* The following will happen on every virtual processor in BigEmulator, not just on once per real processor */ if (CkMyRank() == 0) { CpdBreakPointInit(); } CmiNodeAllBarrier(); // Execute the initcalls registered in modules _initCallTable.enumerateInitCalls(); #if CMK_CHARMDEBUG CpdFinishInitialization(); #endif //CmiNodeAllBarrier(); CkpvAccess(_myStats) = new Stats(); CkpvAccess(_msgPool) = new MsgPool(); CmiNodeAllBarrier(); #if !(__FAULT__) CmiBarrier(); CmiBarrier(); CmiBarrier(); #endif #if CMK_SMP_TRACE_COMMTHREAD _TRACE_BEGIN_COMPUTATION(); #else if (!inCommThread) { _TRACE_BEGIN_COMPUTATION(); } #endif #ifdef ADAPT_SCHED_MEM if(CkMyRank()==0){ memCriticalEntries = new int[numMemCriticalEntries]; int memcnt=0; for(int i=0; i<_entryTable.size(); i++){ if(_entryTable[i]->isMemCritical){ memCriticalEntries[memcnt++] = i; } } } #endif #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) _messageLoggingInit(); #endif #ifndef __BIGSIM__ /* FAULT_EVAC */ CpvAccess(_validProcessors) = new char[CkNumPes()]; for(int vProc=0;vProc<CkNumPes();vProc++){ CpvAccess(_validProcessors)[vProc]=1; } _ckEvacBcastIdx = CkRegisterHandler((CmiHandler)_ckEvacBcast); _ckAckEvacIdx = CkRegisterHandler((CmiHandler)_ckAckEvac); #endif CkpvAccess(startedEvac) = 0; CpvAccess(serializer) = 0; evacuate = 0; CcdCallOnCondition(CcdSIGUSR1,(CcdVoidFn)CkDecideEvacPe,0); #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) CcdCallOnCondition(CcdSIGUSR2,(CcdVoidFn)CkMlogRestart,0); #endif if(_raiseEvac){ processRaiseEvacFile(_raiseEvacFile); /* if(CkMyPe() == 2){ // CcdCallOnConditionKeep(CcdPERIODIC_10s,(CcdVoidFn)CkDecideEvacPe,0); CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000); } if(CkMyPe() == 3){ CcdCallFnAfter((CcdVoidFn)CkDecideEvacPe, 0, 10000); }*/ } if (CkMyRank() == 0) { TopoManager_init(); } CmiNodeAllBarrier(); if (!_replaySystem) { CkFtFn faultFunc_restart = CkRestartMain; if (faultFunc == NULL || faultFunc == faultFunc_restart) { // this is not restart from memory // these two are blocking calls for non-bigsim #if ! CMK_BIGSIM_CHARM CmiInitCPUAffinity(argv); CmiInitMemAffinity(argv); #endif } CmiInitCPUTopology(argv); #if CMK_SHARED_VARS_POSIX_THREADS_SMP if (CmiCpuTopologyEnabled()) { int *pelist; int num; CmiGetPesOnPhysicalNode(0, &pelist, &num); #if !CMK_MULTICORE && !CMK_SMP_NO_COMMTHD // Count communication threads, if present // XXX: Assuming uniformity of node size here num += num/CmiMyNodeSize(); #endif if (!_Cmi_forceSpinOnIdle && num > CmiNumCores()) { if (CmiMyPe() == 0) CmiPrintf("\nCharm++> Warning: the number of SMP threads (%d) is greater than the number of physical cores (%d), so threads will sleep while idling. Use +CmiSpinOnIdle or +CmiSleepOnIdle to control this directly.\n\n", num, CmiNumCores()); CmiLock(CksvAccess(_nodeLock)); if (! _Cmi_sleepOnIdle) _Cmi_sleepOnIdle = 1; CmiUnlock(CksvAccess(_nodeLock)); } } #endif } if(CmiMyPe() == 0) { char *topoFilename; if(CmiGetArgStringDesc(argv,"+printTopo",&topoFilename,"topo file name")) { std::stringstream sstm; sstm << topoFilename << "." << CmiMyPartition(); std::string result = sstm.str(); FILE *fp; fp = fopen(result.c_str(), "w"); if (fp == NULL) { CkPrintf("Error opening %s file, writing to stdout\n", topoFilename); fp = stdout; } TopoManager_printAllocation(fp); fclose(fp); } } #if CMK_USE_PXSHM && ( CMK_CRAYXE || CMK_CRAYXC ) && CMK_SMP // for SMP on Cray XE6 (hopper) it seems pxshm has to be initialized // again after cpuaffinity is done if (CkMyRank() == 0) { CmiInitPxshm(argv); } CmiNodeAllBarrier(); #endif //CldCallback(); #if CMK_BIGSIM_CHARM && CMK_CHARMDEBUG // Register the BG handler for CCS. Notice that this is put into a variable shared by // the whole real processor. This because converse needs to find it. We check that all // virtual processors register the same index for this handler. CpdBgInit(); #endif if (faultFunc) { #if CMK_WITH_STATS if (CkMyPe()==0) _allStats = new Stats*[CkNumPes()]; #endif if (!inCommThread) { CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0); msg->argc = CmiGetArgc(argv); msg->argv = argv; faultFunc(_restartDir, msg); CkFreeMsg(msg); } }else if(CkMyPe()==0){ #if CMK_WITH_STATS _allStats = new Stats*[CkNumPes()]; #endif register size_t i, nMains=_mainTable.size(); for(i=0;i<nMains;i++) /* Create all mainchares */ { register int size = _chareTable[_mainTable[i]->chareIdx]->size; register void *obj = malloc(size); _MEMCHECK(obj); _mainTable[i]->setObj(obj); CkpvAccess(_currentChare) = obj; CkpvAccess(_currentChareType) = _mainTable[i]->chareIdx; register CkArgMsg *msg = (CkArgMsg *)CkAllocMsg(0, sizeof(CkArgMsg), 0); msg->argc = CmiGetArgc(argv); msg->argv = argv; _entryTable[_mainTable[i]->entryIdx]->call(msg, obj); #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) CpvAccess(_currentObj) = (Chare *)obj; #endif } _mainDone = 1; _STATS_RECORD_CREATE_CHARE_N(nMains); _STATS_RECORD_PROCESS_CHARE_N(nMains); for(i=0;i<_readonlyMsgs.size();i++) /* Send out readonly messages */ { register void *roMsg = (void *) *((char **)(_readonlyMsgs[i]->pMsg)); if(roMsg==0) continue; //Pack the message and send it to all other processors register envelope *env = UsrToEnv(roMsg); env->setSrcPe(CkMyPe()); env->setMsgtype(ROMsgMsg); env->setRoIdx(i); CmiSetHandler(env, _initHandlerIdx); CkPackMessage(&env); CmiSyncBroadcast(env->getTotalsize(), (char *)env); CpvAccess(_qd)->create(CkNumPes()-1); //For processor 0, unpack and re-set the global CkUnpackMessage(&env); _processROMsgMsg(env); _numInitMsgs++; } //Determine the size of the RODataMessage PUP::sizer ps; for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(ps); //Allocate and fill out the RODataMessage envelope *env = _allocEnv(RODataMsg, ps.size()); PUP::toMem pp((char *)EnvToUsr(env)); for(i=0;i<_readonlyTable.size();i++) _readonlyTable[i]->pupData(pp); env->setCount(++_numInitMsgs); env->setSrcPe(CkMyPe()); CmiSetHandler(env, _initHandlerIdx); DEBUGF(("[%d,%.6lf] RODataMsg being sent of size %d \n",CmiMyPe(),CmiWallTimer(),env->getTotalsize())); CmiSyncBroadcastAndFree(env->getTotalsize(), (char *)env); CpvAccess(_qd)->create(CkNumPes()-1); _initDone(); } DEBUGF(("[%d,%d%.6lf] inCommThread %d\n",CmiMyPe(),CmiMyRank(),CmiWallTimer(),inCommThread)); // when I am a communication thread, I don't participate initDone. if (inCommThread) { CkNumberHandlerEx(_bocHandlerIdx,(CmiHandlerEx)_processHandler, CkpvAccess(_coreState)); CkNumberHandlerEx(_charmHandlerIdx,(CmiHandlerEx)_processHandler , CkpvAccess(_coreState)); _processBufferedMsgs(); } #if CMK_CHARMDEBUG // Should not use CpdFreeze inside a thread (since this processor is really a user-level thread) if (CpvAccess(cpdSuspendStartup)) { //CmiPrintf("In Parallel Debugging mode .....\n"); CpdFreeze(); } #endif #if __FAULT__ if(killFlag){ readKillFile(); } #endif }
/// Pack/unpack/sizing operator void Event::pup(PUP::er &p) { int msgSize, spawn = 0; SpawnedEvent *tmp = NULL; evID.pup(p); p(fnIdx); p(timestamp); p(done); p(commitBfrLen); p(commitErr); p(srt); p(ert); p(svt); p(evt); // commitBfr if (p.isUnpacking() && (commitBfrLen > 0)) { // unpack non-empty commitBfr commitBfr = new char[commitBfrLen]; p(commitBfr, commitBfrLen); } else if (commitBfrLen > 0) // pack/size non-empty commitBfr p(commitBfr, commitBfrLen); else // unpack empty commitBfr commitBfr = NULL; // msg if (p.isUnpacking()) { // unpack msg p(msgSize); // unpack msgSize if (msgSize > 0) { // if nonzero, unpack msg msg = (eventMsg *)CmiAlloc(msgSize); // allocate space p((char *)msg, msgSize); // unpack into space msg = (eventMsg *)EnvToUsr((envelope *)msg); // reset msg pointer } else // empty message msg = NULL; // set msg to null } else { // pack msg if (msg != NULL) { // msg is not null msgSize = (UsrToEnv(msg))->getTotalsize(); // get msg size p(msgSize); // pack msg size p((char *)(UsrToEnv(msg)), msgSize); // pack from start of envelope } else { // msg is null msgSize = 0; p(msgSize); // pack size of zero } } // spawnedList if (p.isUnpacking()) { // unpack spawnedList p(spawn); // unpack spawn count if (spawn > 0) spawnedList = tmp = new SpawnedEvent(); else spawnedList = NULL; while (spawn > 0) { // unpack each spawned event record tmp->pup(p); tmp->next = NULL; spawn--; if (spawn > 0) { tmp->next = new SpawnedEvent(); tmp = tmp->next; } } } else { // pack/size spawnedList tmp = spawnedList; while (tmp != NULL) { // count the spawn spawn++; tmp = tmp->next; } p(spawn); // pack the spawn count tmp = spawnedList; while (tmp != NULL) { // pack each spawn tmp->pup(p); tmp = tmp->next; } } if (p.isUnpacking()) { cpData = NULL; // to be set later serialCPdata = NULL; serialCPdataSz = 0; } }
static inline void _processROMsgMsg(envelope *env) { if(!CmiMyRank()) { *((char **)(_readonlyMsgs[env->getRoIdx()]->pMsg))=(char *)EnvToUsr(env); } }
static void _exitHandler(envelope *env) { DEBUGF(("exitHandler called on %d msgtype: %d\n", CkMyPe(), env->getMsgtype())); switch(env->getMsgtype()) { case StartExitMsg: CkAssert(CkMyPe()==0); if (!_CkExitFnVec.isEmpty()) { CkExitFn fn = _CkExitFnVec.deq(); fn(); break; } // else goto next case ExitMsg: CkAssert(CkMyPe()==0); if(_exitStarted) { CmiFree(env); return; } _exitStarted = 1; CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler); CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler); env->setMsgtype(ReqStatMsg); env->setSrcPe(CkMyPe()); // if exit in ring, instead of broadcasting, send in ring if (_ringexit){ DEBUGF(("[%d] Ring Exit \n",CkMyPe())); const int stride = CkNumPes()/_ringtoken; int pe = 0; while (pe<CkNumPes()) { CmiSyncSend(pe, env->getTotalsize(), (char *)env); pe += stride; } CmiFree(env); }else{ CmiSyncBroadcastAllAndFree(env->getTotalsize(), (char *)env); } break; case ReqStatMsg: #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_)) _messageLoggingExit(); #endif DEBUGF(("ReqStatMsg on %d\n", CkMyPe())); CkNumberHandler(_charmHandlerIdx,(CmiHandler)_discardHandler); CkNumberHandler(_bocHandlerIdx, (CmiHandler)_discardHandler); /*FAULT_EVAC*/ if(CmiNodeAlive(CkMyPe())){ #if CMK_WITH_STATS _sendStats(); #endif _mainDone = 1; // This is needed because the destructors for // readonly variables will be called when the program // exits. If the destructor is called while _mainDone // is 0, it will assume that the readonly variable was // declared locally. On all processors other than 0, // _mainDone is never set to 1 before the program exits. #if CMK_TRACE_ENABLED if (_ringexit) traceClose(); #endif } if (_ringexit) { int stride = CkNumPes()/_ringtoken; int pe = CkMyPe()+1; if (pe < CkNumPes() && pe % stride != 0) CmiSyncSendAndFree(pe, env->getTotalsize(), (char *)env); else CmiFree(env); } else CmiFree(env); //everyone exits here - there may be issues with leftover messages in the queue #if CMK_WITH_STATS if(CkMyPe()) #endif { DEBUGF(("[%d] Calling converse exit \n",CkMyPe())); ConverseExit(); if(CharmLibInterOperate) CpvAccess(interopExitFlag) = 1; } break; #if CMK_WITH_STATS case StatMsg: CkAssert(CkMyPe()==0); _allStats[env->getSrcPe()] = (Stats*) EnvToUsr(env); _numStatsRecd++; DEBUGF(("StatMsg on %d with %d\n", CkMyPe(), _numStatsRecd)); /*FAULT_EVAC*/ if(_numStatsRecd==CkNumValidPes()) { _printStats(); DEBUGF(("[%d] Calling converse exit \n",CkMyPe())); ConverseExit(); if(CharmLibInterOperate) CpvAccess(interopExitFlag) = 1; } break; #endif default: CmiAbort("Internal Error(_exitHandler): Unknown-msg-type. Contact Developers.\n"); } }
CmiFragmentHeader *PipeBroadcastStrategy::getFragmentHeader(char *msg) { return (CmiFragmentHeader*)EnvToUsr((envelope*)msg); }