Пример #1
0
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;
}
Пример #2
0
  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);
    }
  }
Пример #3
0
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);
    }
}
Пример #4
0
// 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);
}
Пример #5
0
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);
}
Пример #6
0
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;
    }

}
Пример #7
0
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);
}
Пример #8
0
// 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));
}
Пример #9
0
	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);
	}
Пример #10
0
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
}
Пример #11
0
 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);
 }
Пример #12
0
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);
}
Пример #13
0
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);;
}
Пример #14
0
//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));
    }    
}
Пример #15
0
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());
  }
}
Пример #16
0
  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;

  }
Пример #17
0
//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);
}
Пример #18
0
/**
   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);
}
Пример #19
0
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
}
Пример #20
0
/**
  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

}
Пример #21
0
/// 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;
  }
}
Пример #22
0
static inline void _processROMsgMsg(envelope *env)
{
  if(!CmiMyRank()) {
    *((char **)(_readonlyMsgs[env->getRoIdx()]->pMsg))=(char *)EnvToUsr(env);
  }
}
Пример #23
0
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");
  }
}
Пример #24
0
CmiFragmentHeader *PipeBroadcastStrategy::getFragmentHeader(char *msg) {
  return (CmiFragmentHeader*)EnvToUsr((envelope*)msg);
}