00001 
00005 #ifndef _ENVELOPE_H
00006 #define _ENVELOPE_H
00007 
00008 #include <pup.h>
00009 #include <charm.h>
00010 #include <middle.h>
00011 #include <cklists.h>
00012 #include <objid.h>
00013 
00014 #ifndef CkIntbits
00015 #define CkIntbits (sizeof(int)*8)
00016 #endif
00017 
00018 #if CMK_ERROR_CHECKING
00019 #define _SET_USED(env, x) (env)->setUsed((x))
00020 #define _CHECK_USED(env) do { if(env->isUsed()) \
00021                            CmiAbort("Message being re-sent. Aborting...\n"); \
00022                          } while(0)
00023 #else
00024 #define _SET_USED(env, x) do{}while(0)
00025 #define _CHECK_USED(env) do{}while(0)
00026 #endif
00027 
00028 #define CkMsgAlignLength(x)     ALIGN_DEFAULT(x)
00029 #define CkMsgAlignOffset(x)     (CkMsgAlignLength(x)-(x))
00030 #define CkPriobitsToInts(nBits)    ((nBits+CkIntbits-1)/CkIntbits)
00031 
00032 #if CMK_MESSAGE_LOGGING
00033 #define CK_FREE_MSG_MLOG    0x1
00034 #define CK_BYPASS_DET_MLOG  0x2
00035 #define CK_MULTICAST_MSG_MLOG   0x4
00036 #define CK_REDUCTION_MSG_MLOG   0x8
00037 #endif
00038 
00049 class PathHistoryEnvelope {
00050  protected:
00051   
00052   int sender_history_table_idx;
00053   double totalTime;
00054  public:
00055   double getTotalTime() const{ return totalTime; }
00056   int get_sender_history_table_idx() const{ return sender_history_table_idx; }
00057   void set_sender_history_table_idx(int i) { sender_history_table_idx = i; }
00058   PathHistoryEnvelope(){ 
00059     reset(); 
00060   }
00061   double getTime() const{ return totalTime; }
00062   void setTime(double t){ totalTime = t; }
00063   void pup(PUP::er &p) {
00064     p | sender_history_table_idx;
00065     p | totalTime;
00066   } 
00067   void reset();
00068   void print() const;
00070   void printHTMLToString(char* buf) const{
00071     buf[0] = '\0';
00072     sprintf(buf+strlen(buf), "Path Time=%lf<br> Sender idx=%d", (double)totalTime, (int)sender_history_table_idx);
00073   }
00075   int getNumUsed() const;
00077   int getUsedCount(int idx) const;
00079   int getUsedEp(int idx) const;
00080   int getEpCount(int ep) const;
00081   void incrementTotalTime(double time);
00082   
00083   void setDebug100();
00084 };
00089 typedef unsigned int   UInt;
00090 typedef unsigned short UShort;
00091 typedef unsigned char  UChar;
00092 
00093 #include "charm.h" 
00094 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
00095 #include "ckobjid.h" 
00096 #endif
00097 
00102 CkpvExtern(int, envelopeEventID);
00103 
00142 namespace ck {
00143 
00144   namespace impl {
00148     union u_type {
00149       struct s_chare {  
00150         void *ptr;      
00151         UInt forAnyPe;  
00152         int  bype;      
00153       } chare;
00154       struct s_group {         
00155         CkGroupID g;           
00156         CkNodeGroupID rednMgr; 
00157         int epoch;             
00158         UShort arrayEp;        
00159       } group;
00160       struct s_array{             
00161         CmiUInt8 id;              
00162         CkGroupID arr;            
00163 #if CMK_SMP_TRACE_COMMTHREAD
00164         UInt srcpe;
00165 #endif
00166         UChar hopCount;           
00167         UChar ifNotThere;         
00168       } array;
00169       struct s_roData {    
00170         UInt count;
00171       } roData;
00172       struct s_roMsg {     
00173         UInt roIdx;
00174       } roMsg;
00175     };
00176 
00177     struct s_attribs {  
00178       UChar msgIdx;     
00179       UChar mtype;      
00180       UChar queueing:4; 
00181       UChar isPacked:1; 
00182       UChar isUsed:1;   
00183       UChar isVarSysMsg:1; 
00184     };
00185 
00186   }
00187 }
00188 
00189 #if (defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
00190 #define CMK_ENVELOPE_FT_FIELDS                           \
00191   CkObjID sender;                                        \
00192   CkObjID recver;                                        \
00193   MCount SN;                                             \
00194   int incarnation;                                       \
00195   int flags;                                             \
00196   UInt piggyBcastIdx;
00197 #elif defined(_FAULT_CAUSAL_)
00198 #define CMK_ENVELOPE_FT_FIELDS                           \
00199   CkObjID sender;                                        \
00200   CkObjID recver;                                        \
00201   MCount SN;                                             \
00202   MCount TN;                                             \
00203   int incarnation;                                       \
00204   int flags;                                             \
00205   UInt piggyBcastIdx;
00206 #else
00207 #define CMK_ENVELOPE_FT_FIELDS
00208 #endif
00209 
00210 #if CMK_REPLAYSYSTEM || CMK_TRACE_ENABLED
00211 #define CMK_ENVELOPE_OPTIONAL_FIELDS                                           \
00212   UInt   event;        
00213 #else
00214 #define CMK_ENVELOPE_OPTIONAL_FIELDS
00215 #endif
00216 
00217 #define CMK_ENVELOPE_FIELDS                                                    \
00218              \
00219   char   core[CmiReservedHeaderSize];                                          \
00220   UInt   pe;                                             \
00221   ck::impl::u_type type;          \
00222   UInt   totalsize;     \
00223   CMK_ENVELOPE_OPTIONAL_FIELDS                                                 \
00224   CMK_REFNUM_TYPE ref;                           \
00225   UShort priobits;        \
00226   UShort groupDepNum;                        \
00227   UShort epIdx;                                       \
00228   ck::impl::s_attribs attribs;
00229 
00230 class envelope {
00231 private:
00232 
00233     class envelopeSizeHelper {
00234       CMK_ENVELOPE_FIELDS
00235       CMK_ENVELOPE_FT_FIELDS
00236     };
00237 
00238     #ifdef __clang__
00239     #pragma GCC diagnostic push
00240     #pragma GCC diagnostic ignored "-Wunused-private-field"
00241     #endif
00242     CMK_ENVELOPE_FIELDS
00243     #ifdef __clang__
00244     #pragma GCC diagnostic pop
00245     #endif
00246 
00247 public:
00248 
00249     CMK_ENVELOPE_FT_FIELDS
00250 
00251     #if defined(__GNUC__) || defined(__clang__)
00252     #pragma GCC diagnostic push
00253     #pragma GCC diagnostic ignored "-Wpedantic"
00254     #if defined(__clang__)
00255     #pragma GCC diagnostic ignored "-Wunused-private-field"
00256     #endif
00257     #endif
00258     
00259     UChar align[CkMsgAlignOffset(sizeof(envelopeSizeHelper))];
00260     #if defined(__GNUC__) || defined(__clang__)
00261     #pragma GCC diagnostic pop
00262     #endif
00263 
00264     void pup(PUP::er &p);
00265 #if CMK_REPLAYSYSTEM || CMK_TRACE_ENABLED
00266     UInt   getEvent(void) const { return event; }
00267     void   setEvent(const UInt e) { event = e; }
00268 #endif
00269     CMK_REFNUM_TYPE   getRef(void) const { return ref; }
00270     void   setRef(const CMK_REFNUM_TYPE r) { ref = r; }
00271     UChar  getQueueing(void) const { return attribs.queueing; }
00272     void   setQueueing(const UChar q) { attribs.queueing=q; }
00273     UChar  getMsgtype(void) const { return attribs.mtype; }
00274     void   setMsgtype(const UChar m) { attribs.mtype = m; }
00275 #if CMK_ERROR_CHECKING
00276     UChar  isUsed(void) const { return attribs.isUsed; }
00277     void   setUsed(const UChar u) { attribs.isUsed=u; }
00278 #else 
00279     inline void setUsed(const UChar u) {}
00280 #endif
00281     UChar  getMsgIdx(void) const { return attribs.msgIdx; }
00282     void   setMsgIdx(const UChar idx) { attribs.msgIdx = idx; }
00283     UInt   getTotalsize(void) const { return totalsize; }
00284     void   setTotalsize(const UInt s) { totalsize = s; }
00285     UInt   getUsersize(void) const { 
00286       return totalsize - getGroupDepSize() - getPrioBytes() - sizeof(envelope); 
00287     }
00288     void   setUsersize(const UInt s) {
00289       if (s == getUsersize()) {
00290         return;
00291       }
00292       CkAssert(s < getUsersize());
00293       UInt newPrioOffset = sizeof(envelope) + CkMsgAlignLength(s);
00294       UInt newTotalsize = newPrioOffset + getPrioBytes() + getGroupDepSize();
00295       void *newPrioPtr = (void *) ((char *) this + newPrioOffset); 
00296       
00297       memmove(newPrioPtr, getPrioPtr(), getPrioBytes()); 
00298       setTotalsize(newTotalsize); 
00299     }
00300 
00301     
00302     void shrinkUsersize(const UInt s) {
00303       CkAssert(s <= getUsersize());
00304       setUsersize(getUsersize() - s);
00305     }
00306 
00307     UChar  isPacked(void) const { return attribs.isPacked; }
00308     void   setPacked(const UChar p) { attribs.isPacked = p; }
00309     UChar  isVarSysMsg(void) const { return attribs.isVarSysMsg; }
00310     void   setIsVarSysMsg(const UChar d) { attribs.isVarSysMsg = d; }
00311     UShort getPriobits(void) const { return priobits; }
00312     void   setPriobits(const UShort p) { priobits = p; }
00313     UShort getPrioWords(void) const { return CkPriobitsToInts(priobits); }
00314     UShort getPrioBytes(void) const { return getPrioWords()*sizeof(int); }
00315     void*  getPrioPtr(void) const { 
00316       return (void *)((char *)this + totalsize - getGroupDepSize() - getPrioBytes());
00317     }
00318     void* getGroupDepPtr(void) const {
00319       return (void *)((char *)this + totalsize - getGroupDepSize());
00320     }
00321     static envelope *alloc(const UChar type, const UInt size=0, const UShort prio=0, const GroupDepNum groupDepNumRequest=GroupDepNum{})
00322     {
00323 #if CMK_LOCKLESS_QUEUE
00324       CkAssert(type>=NewChareMsg && type<LAST_CK_ENVELOPE_TYPE);
00325 #else
00326       CkAssert(type>=NewChareMsg && type<=ForArrayEltMsg);
00327 #endif
00328 #if CMK_USE_STL_MSGQ
00329       
00330       CkAssert(sizeof(CMK_MSG_PRIO_TYPE) >= sizeof(int)*CkPriobitsToInts(prio));
00331 #endif
00332 
00333       UInt tsize = sizeof(envelope)+ 
00334                    CkMsgAlignLength(size)+
00335                    sizeof(int)*CkPriobitsToInts(prio) +
00336                    sizeof(CkGroupID)*(int)groupDepNumRequest;
00337 
00338       
00339 
00340       envelope *env = (envelope *)CmiAlloc(tsize);
00341 #if CMK_REPLAYSYSTEM
00342       
00343       memset(env, 0, sizeof(envelope));
00344       env->setEvent(++CkpvAccess(envelopeEventID));
00345 #endif
00346       env->setMsgtype(type);
00347       env->totalsize = tsize;
00348       env->priobits = prio;
00349       env->setPacked(0);
00350       env->setGroupDepNum((int)groupDepNumRequest);
00351       _SET_USED(env, 0);
00352       env->setEpIdx(0);
00353       env->setIsVarSysMsg(0);
00354 
00355 #if USE_CRITICAL_PATH_HEADER_ARRAY
00356       env->pathHistory.reset();
00357 #endif
00358 
00359 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
00360       env->sender.type = TypeInvalid;
00361       env->recver.type = TypeInvalid;
00362       env->SN = 0;
00363       env->flags = 0;
00364 #if defined(_FAULT_CAUSAL_)
00365       env->TN = 0;
00366 #endif
00367       env->incarnation = -1;
00368 #endif
00369 
00370       return env;
00371     }
00372     void reset() {
00373 #if CMK_REPLAYSYSTEM
00374       setEvent(++CkpvAccess(envelopeEventID));
00375 #endif
00376       memset(getGroupDepPtr(), 0, getGroupDepSize());
00377     }
00378     UShort getEpIdx(void) const { return epIdx; }
00379     void   setEpIdx(const UShort idx) { epIdx = idx; }
00380     UInt   getSrcPe(void) const { return pe; }
00381     void   setSrcPe(const UInt s) { pe = s; }
00382     static void setSrcPe(char *env, const UInt s) { ((envelope*)env)->setSrcPe(s); }
00383 
00384 
00385     UInt   getCount(void) const { 
00386       CkAssert(getMsgtype()==RODataMsg); return type.roData.count; 
00387     }
00388     void   setCount(const UInt c) { 
00389       CkAssert(getMsgtype()==RODataMsg); type.roData.count = c; 
00390     }
00391     UInt   getRoIdx(void) const { 
00392       CkAssert(getMsgtype()==ROMsgMsg); return type.roMsg.roIdx; 
00393     }
00394     void   setRoIdx(const UInt r) { 
00395       CkAssert(getMsgtype()==ROMsgMsg); type.roMsg.roIdx = r; 
00396     }
00397     
00398  
00399     UInt isForAnyPE(void) const {
00400       CkAssert(getMsgtype()==NewChareMsg || getMsgtype()==NewVChareMsg); 
00401       return type.chare.forAnyPe; 
00402     }
00403     void setForAnyPE(UInt f) { 
00404       CkAssert(getMsgtype()==NewChareMsg || getMsgtype()==NewVChareMsg); 
00405       type.chare.forAnyPe = f; 
00406     }
00407     void*  getVidPtr(void) const {
00408       CkAssert(getMsgtype()==NewVChareMsg || getMsgtype()==ForVidMsg
00409           || getMsgtype()==FillVidMsg ||  getMsgtype()==DeleteVidMsg);
00410       return type.chare.ptr;
00411     }
00412     void   setVidPtr(void *p) {
00413       CkAssert(getMsgtype()==NewVChareMsg || getMsgtype()==ForVidMsg
00414           || getMsgtype()==FillVidMsg ||  getMsgtype()==DeleteVidMsg);
00415       type.chare.ptr = p;
00416     }
00417     void*  getObjPtr(void) const { 
00418       CkAssert(getMsgtype()==ForChareMsg); return type.chare.ptr; 
00419     }
00420     void   setObjPtr(void *p) { 
00421       CkAssert(getMsgtype()==ForChareMsg); type.chare.ptr = p; 
00422     }
00423     UInt getByPe(void) const {
00424       CkAssert(getMsgtype()==NewChareMsg || getMsgtype()==NewVChareMsg); 
00425       return type.chare.bype; 
00426     }
00427     void setByPe(UInt pe) { 
00428       CkAssert(getMsgtype()==NewChareMsg || getMsgtype()==NewVChareMsg); 
00429       type.chare.bype = pe; 
00430     }
00431 
00432 
00433     CkGroupID   getGroupNum(void) const {
00434       CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
00435           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
00436       return type.group.g;
00437     }
00438     void   setGroupNum(const CkGroupID g) {
00439       CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
00440           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
00441       type.group.g = g;
00442     }
00443     void setGroupEpoch(int epoch) { CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==NodeBocInitMsg); type.group.epoch=epoch; }
00444     int getGroupEpoch(void) const { CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==NodeBocInitMsg); return type.group.epoch; }
00445     void setRednMgr(CkNodeGroupID r){ CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
00446           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
00447  type.group.rednMgr = r; }
00448     CkNodeGroupID getRednMgr(){       CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
00449           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
00450  return type.group.rednMgr; }
00451     UShort getGroupDepSize() const { return groupDepNum*sizeof(CkGroupID); }
00452     UShort getGroupDepNum() const { return groupDepNum; }
00453     void setGroupDepNum(const UShort &r) { groupDepNum = r; }
00454     CkGroupID getGroupDep(int index=0) { return *((CkGroupID *)getGroupDepPtr() + index); }
00455     void setGroupDep(const CkGroupID &r, int index=0) {
00456       *(((CkGroupID *)getGroupDepPtr())+ index) = r;
00457     }
00458 
00459 
00460     CkGroupID getArrayMgr(void) const { 
00461       if (getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg)
00462     return type.array.arr;
00463       else
00464             CkAbort("Cannot return ArrayID from msg for non-array entity");
00465     
00466       return type.array.arr;
00467     }
00468     void setArrayMgr(const CkGroupID gid) { CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg);  type.array.arr = gid; }
00469     int getArrayMgrIdx(void) const {CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg);  return type.array.arr.idx;}
00470     UShort &getsetArrayEp(void) {return epIdx;}
00471     UShort &getsetArrayBcastEp(void) {return type.group.arrayEp;}
00472 #if CMK_SMP_TRACE_COMMTHREAD
00473     UInt &getsetArraySrcPe(void) {return type.array.srcpe;}
00474 #else
00475     UInt &getsetArraySrcPe(void) {return pe;}
00476 #endif
00477     UChar &getsetArrayHops(void) { CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg); return type.array.hopCount;}
00478     int getArrayIfNotThere(void) const { CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg); return type.array.ifNotThere;}
00479     void setArrayIfNotThere(int nt) { CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg); type.array.ifNotThere=nt;}
00480 
00481     void setRecipientID(ck::ObjID objid)
00482     {
00483       CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg);
00484       type.array.id = objid.getID();
00485     }
00486 
00487     CmiUInt8 getRecipientID() const
00488     {
00489       CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg);
00490       return type.array.id;
00491     }
00492 
00493 #if USE_CRITICAL_PATH_HEADER_ARRAY
00494  public:
00498     PathHistoryEnvelope pathHistory;
00499 #endif
00500 
00501 };
00502 
00503 
00504 inline envelope *UsrToEnv(const void *const msg) {
00505   return (envelope *)((intptr_t)msg - sizeof(envelope));
00506 }
00507 
00508 inline void *EnvToUsr(const envelope *const env) {
00509   return (void *)((intptr_t)env + sizeof(envelope));
00510 }
00511 
00512 inline envelope *_allocEnv(const int msgtype, const int size=0, const int prio=0, const GroupDepNum groupDepNum=GroupDepNum{}) {
00513   return envelope::alloc(msgtype,size,prio,groupDepNum);
00514 }
00515 
00516 inline void *_allocMsg(const int msgtype, const int size, const int prio=0, const GroupDepNum groupDepNum=GroupDepNum{}) {
00517   return EnvToUsr(envelope::alloc(msgtype,size,prio,groupDepNum));
00518 }
00519 
00520 inline void _resetEnv(envelope *env) {
00521   env->reset();
00522 }
00523 
00524 #if CMK_REPLAYSYSTEM
00525 inline void setEventID(envelope *env){
00526   env->setEvent(++CkpvAccess(envelopeEventID));
00527 }
00528 #endif
00529 
00532 extern UChar   _defaultQueueing;
00533 
00534 extern void CkPackMessage(envelope **pEnv);
00535 extern void CkUnpackMessage(envelope **pEnv);
00536 
00537 class MsgPool: public SafePool<void *> {
00538 private:
00539     static void *_alloc(void) {
00540       
00541       envelope *env = _allocEnv(ForChareMsg,0,0,GroupDepNum{});
00542       env->setQueueing(_defaultQueueing);
00543       env->setMsgIdx(0);
00544       return EnvToUsr(env);
00545     }
00546     static void _reset(void* m) {
00547       envelope *env = UsrToEnv(m);
00548       _resetEnv(env);
00549     }
00550 public:
00551     MsgPool():SafePool<void*>(_alloc, CkFreeMsg, _reset) {}
00552 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
00553         void *get(void){
00554             return allocfn();
00555         }
00556         void put(void *m){
00557         }
00558 #endif
00559 };
00560 
00561 CkpvExtern(MsgPool*, _msgPool);
00562 
00563 #endif