Critical path header changes for the pics merge
[charm.git] / src / ck-core / envelope.h
1 /**
2  @defgroup CkEnvelope
3  \brief  Charm++ message header.
4 */
5 #ifndef _ENVELOPE_H
6 #define _ENVELOPE_H
7
8 #include <pup.h>
9 #include <charm.h>
10 #include <middle.h>
11 #include <ckarrayindex.h>
12 #include <cklists.h>
13 #include <objid.h>
14
15 #ifndef CkIntbits
16 #define CkIntbits (sizeof(int)*8)
17 #endif
18
19 #if CMK_ERROR_CHECKING
20 #define _SET_USED(env, x) (env)->setUsed((x))
21 #define _CHECK_USED(env) do { if(env->isUsed()) \
22                            CmiAbort("Message being re-sent. Aborting...\n"); \
23                          } while(0)
24 #else
25 #define _SET_USED(env, x) do{}while(0)
26 #define _CHECK_USED(env) do{}while(0)
27 #endif
28
29 #define CkMsgAlignLength(x)     ALIGN_DEFAULT(x)
30 #define CkMsgAlignOffset(x)     (CkMsgAlignLength(x)-(x))
31 #define CkPriobitsToInts(nBits)    ((nBits+CkIntbits-1)/CkIntbits)
32
33 #if CMK_MESSAGE_LOGGING
34 #define CK_FREE_MSG_MLOG        0x1
35 #define CK_BYPASS_DET_MLOG      0x2
36 #define CK_MULTICAST_MSG_MLOG   0x4
37 #define CK_REDUCTION_MSG_MLOG   0x8
38 #endif
39
40 /**
41     \addtogroup CriticalPathFramework 
42     @{
43 */
44
45 /** A class that is used to track the entry points and other information 
46     about a critical path as a charm++ program executes.
47
48     This class won't do useful things unless USE_CRITICAL_PATH_HEADER_ARRAY is defined
49 */
50 class PathHistoryEnvelope {
51  protected:
52   // When passing paths forward, store information on PEs, in backward pass, lookup necessary information
53   int sender_history_table_idx;
54   double totalTime;
55  public:
56   double getTotalTime() const{ return totalTime; }
57   int get_sender_history_table_idx() const{ return sender_history_table_idx; }
58   void set_sender_history_table_idx(int i) { sender_history_table_idx = i; }
59   PathHistoryEnvelope(){ 
60     reset(); 
61   }
62   double getTime() const{ return totalTime; }
63   void setTime(double t){ totalTime = t; }
64   void pup(PUP::er &p) {
65     p | sender_history_table_idx;
66     p | totalTime;
67   } 
68   void reset();
69   void print() const;
70   /// Write a description of the path into the beginning of the provided buffer. The buffer ought to be large enough.
71   void printHTMLToString(char* buf) const{
72     buf[0] = '\0';
73     sprintf(buf+strlen(buf), "Path Time=%lf<br> Sender idx=%d", (double)totalTime, (int)sender_history_table_idx);
74   }
75   /// The number of available EP counts 
76   int getNumUsed() const;
77   /// Return the count value for the idx'th available EP  
78   int getUsedCount(int idx) const;
79   /// Return the idx'th available EP 
80   int getUsedEp(int idx) const;
81   int getEpCount(int ep) const;
82   void incrementTotalTime(double time);
83   //  void createPath(envelope *originatingMsg);
84   void setDebug100();
85 };
86 /** @} */
87
88
89
90 typedef unsigned int   UInt;
91 typedef unsigned short UShort;
92 typedef unsigned char  UChar;
93
94 #include "charm.h" // for CkGroupID, and CkEnvelopeType
95 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
96 #include "ckobjid.h" //for the ckobjId
97 #endif
98
99 /**
100 @addtogroup CkEnvelope
101 */
102
103 CkpvExtern(int, envelopeEventID);
104
105 struct s_objid_o {
106   ck::ObjID id;              /// <ck::ObjID if it could be in a union
107 #if CMK_SMP_TRACE_COMMTHREAD
108   UInt srcpe;
109 #endif
110   UChar hopCount;           ///< number of times message has been routed
111   UChar ifNotThere;         ///< what to do if array element is missing
112 };
113
114
115 /**
116 @{
117 The class envelope defines a Charm++ message's header. The first
118 'CmiReservedHeaderSize' bytes of memory is exclusively reserved for Converse
119 header, which is defined in converse.h and platform specific config files.
120
121 After Charm++ envelope comes the payload, i.e. a variable-length amount of user
122 data. Following the user data, optionally, a variable number of bits of
123 priority data can be stored at the end. Function
124 envelope::alloc(msgtype,size,prio) is always used to allocate the whole
125 message. Note that this memory layout must be observed.
126
127 The following are a few terms that are used often:
128
129 <pre>
130  Envelope pointer        \
131  Converse message pointer -> [ [ Converse envelope ]       ]
132                              [       Charm envelope        ] 
133  User message pointer     -> [ User data/payload ... ]
134  Priority pointer         -> [ Priority ints ... ]
135 </pre>
136
137 The "message pointers" passed to and from users bypass the envelope and point
138 *directly* to the user data--the routine "EnvToUsr" below adjusts an envelope
139 (or converse message) pointer into this user message pointer.  There is a
140 corresponding routine "UsrToEnv" which takes the user data pointer and returns
141 a pointer to the envelope/converse message.
142
143 Unfortunately, in the guts of Charm++ it's not always clear whether you've been
144 given a converse or user message pointer, as both tend to be passed as void *.
145 Confusing the two will invariably result in data corruption and bizarre
146 crashes.
147
148 FIXME: Make CkMessage inherit from envelope,
149 which would unify converse, envelope, and 
150 user message pointers.
151 */
152
153 namespace ck {
154
155   namespace impl {
156     /**
157        These structures store the type-specific message information.
158     */
159     union u_type {
160       struct s_chare {  // NewChareMsg, NewVChareMsg, ForChareMsg, ForVidMsg, FillVidMsg
161         void *ptr;      ///< object pointer
162         UInt forAnyPe;  ///< Used only by newChare
163         int  bype;      ///< created by this pe
164       } chare;
165       struct s_group {         // NodeBocInitMsg, BocInitMsg, ForNodeBocMsg, ForBocMsg
166         CkGroupID g;           ///< GroupID
167         CkNodeGroupID rednMgr; ///< Reduction manager for this group (constructor only!)
168         CkGroupID dep;         ///< create after dep is created (constructor only!)
169         int epoch;             ///< "epoch" this group was created during (0--mainchare, 1--later)
170         UShort arrayEp;        ///< Used only for array broadcasts
171       } group;
172       struct s_array{             ///< For arrays only (ArrayEltInitMsg, ForArrayEltMsg)
173         CkArrayIndexBase index; ///< Array element index
174         int listenerData[CK_ARRAYLISTENER_MAXLEN]; ///< For creation
175         CkGroupID arr;            ///< Array manager GID
176 #if CMK_SMP_TRACE_COMMTHREAD
177         UInt srcpe;
178 #endif
179         UChar hopCount;           ///< number of times message has been routed
180         UChar ifNotThere;         ///< what to do if array element is missing
181       } array;
182       struct s_objid {
183         CmiUInt8 id;              /// <ck::ObjID if it could be in a union
184 #if CMK_SMP_TRACE_COMMTHREAD
185         UInt srcpe;
186 #endif
187         UChar hopCount;           ///< number of times message has been routed
188         UChar ifNotThere;         ///< what to do if array element is missing
189       } objid;
190       struct s_roData {    ///< RODataMsg for readonly data type
191         UInt count;
192       } roData;
193       struct s_roMsg {     ///< ROMsgMsg for readonlys defined in ci files
194         UInt roIdx;
195       } roMsg;
196     };
197
198     struct s_attribs {  // Packed bitwise struct
199       UChar msgIdx;     ///< Usertype of message (determines pack routine)
200       UChar mtype;      ///< e.g., ForBocMsg
201       UChar queueing:4; ///< Queueing strategy (FIFO, LIFO, PFIFO, ...)
202       UChar isPacked:1; ///< If true, message must be unpacked before use
203       UChar isUsed:1;   ///< Marker bit to prevent message re-send.
204     };
205
206   }
207 }
208
209 #if (defined(_FAULT_MLOG_) && !defined(_FAULT_CAUSAL_))
210 #define CMK_ENVELOPE_FT_FIELDS                           \
211   CkObjID sender;                                        \
212   CkObjID recver;                                        \
213   MCount SN;                                             \
214   int incarnation;                                       \
215   int flags;                                             \
216   UInt piggyBcastIdx;
217 #elif defined(_FAULT_CAUSAL_)
218 #define CMK_ENVELOPE_FT_FIELDS                           \
219   CkObjID sender;                                        \
220   CkObjID recver;                                        \
221   MCount SN;                                             \
222   MCount TN;                                             \
223   int incarnation;                                       \
224   int flags;                                             \
225   UInt piggyBcastIdx;
226 #else
227 #define CMK_ENVELOPE_FT_FIELDS
228 #endif
229
230 #if CMK_REPLAYSYSTEM || CMK_TRACE_ENABLED
231 #define CMK_ENVELOPE_OPTIONAL_FIELDS                                           \
232   UInt   event;        /* used by projections and record-replay */
233 #else
234 #define CMK_ENVELOPE_OPTIONAL_FIELDS
235 #endif
236
237 #define CMK_ENVELOPE_FIELDS                                                    \
238   /* Converse message envelope, Must be first field in this class */           \
239   char   core[CmiReservedHeaderSize];                                          \
240   ck::impl::u_type type; /* Depends on message type (attribs.mtype) */         \
241   UInt   pe;           /* source processor */                                  \
242   UInt   totalsize;    /* Byte count from envelope start to end of priobits */ \
243   CMK_ENVELOPE_OPTIONAL_FIELDS                                                 \
244   CMK_REFNUM_TYPE ref; /* Used by futures and SDAG */                          \
245   UShort priobits;     /* Number of bits of priority data after user data */   \
246   UShort epIdx;        /* Entry point to call */                               \
247   ck::impl::s_attribs attribs;
248
249 class envelope {
250 private:
251
252     class envelopeSizeHelper {
253       CMK_ENVELOPE_FIELDS
254       CMK_ENVELOPE_FT_FIELDS
255     };
256
257     CMK_ENVELOPE_FIELDS
258
259 public:
260
261     CMK_ENVELOPE_FT_FIELDS
262
263     // padding to ensure ALIGN_BYTES alignment
264     UChar align[CkMsgAlignOffset(sizeof(envelopeSizeHelper))];
265
266     void pup(PUP::er &p);
267 #if CMK_REPLAYSYSTEM || CMK_TRACE_ENABLED
268     UInt   getEvent(void) const { return event; }
269     void   setEvent(const UInt e) { event = e; }
270 #endif
271     CMK_REFNUM_TYPE   getRef(void) const { return ref; }
272     void   setRef(const CMK_REFNUM_TYPE r) { ref = r; }
273     UChar  getQueueing(void) const { return attribs.queueing; }
274     void   setQueueing(const UChar q) { attribs.queueing=q; }
275     UChar  getMsgtype(void) const { return attribs.mtype; }
276     void   setMsgtype(const UChar m) { attribs.mtype = m; }
277 #if CMK_ERROR_CHECKING
278     UChar  isUsed(void) { return attribs.isUsed; }
279     void   setUsed(const UChar u) { attribs.isUsed=u; }
280 #else /* CMK_ERROR_CHECKING */
281     inline void setUsed(const UChar u) {}
282 #endif
283     UChar  getMsgIdx(void) const { return attribs.msgIdx; }
284     void   setMsgIdx(const UChar idx) { attribs.msgIdx = idx; }
285     UInt   getTotalsize(void) const { return totalsize; }
286     void   setTotalsize(const UInt s) { totalsize = s; }
287     UInt   getUsersize(void) const { 
288       return totalsize - getPrioBytes() - sizeof(envelope); 
289     }
290     void   setUsersize(const UInt s) {
291       if (s == getUsersize()) {
292         return;
293       }
294       CkAssert(s < getUsersize());
295       UInt newPrioOffset = sizeof(envelope) + CkMsgAlignLength(s);
296       UInt newTotalsize = newPrioOffset + getPrioBytes();
297       void *newPrioPtr = (void *) ((char *) this + newPrioOffset); 
298       // use memmove instead of memcpy in case memory areas overlap
299       memmove(newPrioPtr, getPrioPtr(), getPrioBytes()); 
300       setTotalsize(newTotalsize); 
301     }
302
303     // s specifies number of bytes to remove from user portion of message
304     void shrinkUsersize(const UInt s) {
305       CkAssert(s <= getUsersize());
306       setUsersize(getUsersize() - s);
307     }
308
309     UChar  isPacked(void) const { return attribs.isPacked; }
310     void   setPacked(const UChar p) { attribs.isPacked = p; }
311     UShort getPriobits(void) const { return priobits; }
312     void   setPriobits(const UShort p) { priobits = p; }
313     UShort getPrioWords(void) const { return CkPriobitsToInts(priobits); }
314     UShort getPrioBytes(void) const { return getPrioWords()*sizeof(int); }
315     void*  getPrioPtr(void) const { 
316       return (void *)((char *)this + totalsize - getPrioBytes());
317     }
318     static envelope *alloc(const UChar type, const UInt size=0, const UShort prio=0)
319     {
320       CkAssert(type>=NewChareMsg && type<=ForArrayEltMsg);
321 #if CMK_USE_STL_MSGQ
322       // Ideally, this should be a static compile-time assert. However we need API changes for that
323       CkAssert(sizeof(CMK_MSG_PRIO_TYPE) >= sizeof(int)*CkPriobitsToInts(prio));
324 #endif
325
326       UInt tsize = sizeof(envelope)+ 
327             CkMsgAlignLength(size)+
328             sizeof(int)*CkPriobitsToInts(prio);
329       envelope *env = (envelope *)CmiAlloc(tsize);
330 #if CMK_REPLAYSYSTEM
331       //for record-replay
332       memset(env, 0, sizeof(envelope));
333       env->setEvent(++CkpvAccess(envelopeEventID));
334 #endif
335       env->setMsgtype(type);
336       env->totalsize = tsize;
337       env->priobits = prio;
338       env->setPacked(0);
339       env->type.group.dep.setZero();
340       _SET_USED(env, 0);
341       env->setRef(0);
342       env->setEpIdx(0);
343
344 #if USE_CRITICAL_PATH_HEADER_ARRAY
345       env->pathHistory.reset();
346 #endif
347
348 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
349       env->sender.type = TypeInvalid;
350       env->recver.type = TypeInvalid;
351       env->SN = 0;
352       env->flags = 0;
353 #if defined(_FAULT_CAUSAL_)
354       env->TN = 0;
355 #endif
356           env->incarnation = -1;
357 #endif
358
359       return env;
360     }
361     void reset() {
362 #if CMK_REPLAYSYSTEM
363       setEvent(++CkpvAccess(envelopeEventID));
364 #endif
365       type.group.dep.setZero();
366     }
367     UShort getEpIdx(void) const { return epIdx; }
368     void   setEpIdx(const UShort idx) { epIdx = idx; }
369     UInt   getSrcPe(void) const { return pe; }
370     void   setSrcPe(const UInt s) { pe = s; }
371     static void setSrcPe(char *env, const UInt s) { ((envelope*)env)->setSrcPe(s); }
372
373 // Readonly-specific fields
374     UInt   getCount(void) const { 
375       CkAssert(getMsgtype()==RODataMsg); return type.roData.count; 
376     }
377     void   setCount(const UInt c) { 
378       CkAssert(getMsgtype()==RODataMsg); type.roData.count = c; 
379     }
380     UInt   getRoIdx(void) const { 
381       CkAssert(getMsgtype()==ROMsgMsg); return type.roMsg.roIdx; 
382     }
383     void   setRoIdx(const UInt r) { 
384       CkAssert(getMsgtype()==ROMsgMsg); type.roMsg.roIdx = r; 
385     }
386     
387  // Chare-specific fields
388     UInt isForAnyPE(void) { 
389       CkAssert(getMsgtype()==NewChareMsg || getMsgtype()==NewVChareMsg); 
390       return type.chare.forAnyPe; 
391     }
392     void setForAnyPE(UInt f) { 
393       CkAssert(getMsgtype()==NewChareMsg || getMsgtype()==NewVChareMsg); 
394       type.chare.forAnyPe = f; 
395     }
396     void*  getVidPtr(void) const {
397       CkAssert(getMsgtype()==NewVChareMsg || getMsgtype()==ForVidMsg
398           || getMsgtype()==FillVidMsg ||  getMsgtype()==DeleteVidMsg);
399       return type.chare.ptr;
400     }
401     void   setVidPtr(void *p) {
402       CkAssert(getMsgtype()==NewVChareMsg || getMsgtype()==ForVidMsg
403           || getMsgtype()==FillVidMsg ||  getMsgtype()==DeleteVidMsg);
404       type.chare.ptr = p;
405     }
406     void*  getObjPtr(void) const { 
407       CkAssert(getMsgtype()==ForChareMsg); return type.chare.ptr; 
408     }
409     void   setObjPtr(void *p) { 
410       CkAssert(getMsgtype()==ForChareMsg); type.chare.ptr = p; 
411     }
412     UInt getByPe(void) { 
413       CkAssert(getMsgtype()==NewChareMsg || getMsgtype()==NewVChareMsg); 
414       return type.chare.bype; 
415     }
416     void setByPe(UInt pe) { 
417       CkAssert(getMsgtype()==NewChareMsg || getMsgtype()==NewVChareMsg); 
418       type.chare.bype = pe; 
419     }
420
421 // Group-specific fields
422     CkGroupID   getGroupNum(void) const {
423       CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
424           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
425       return type.group.g;
426     }
427     void   setGroupNum(const CkGroupID g) {
428       CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
429           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
430       type.group.g = g;
431     }
432     void setGroupEpoch(int epoch) { CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==NodeBocInitMsg); type.group.epoch=epoch; }
433     int getGroupEpoch(void) { CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==NodeBocInitMsg); return type.group.epoch; }
434     void setRednMgr(CkNodeGroupID r){ CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
435           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
436  type.group.rednMgr = r; }
437     CkNodeGroupID getRednMgr(){       CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
438           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
439  return type.group.rednMgr; }
440     CkGroupID getGroupDep(){       CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
441           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
442  return type.group.dep; }
443     void setGroupDep(const CkGroupID &r){       CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
444           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
445       type.group.dep = r; }
446
447 // Array-specific fields
448     CkGroupID getArrayMgr(void) const { 
449       if (getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg)
450         return type.array.arr;
451       else if (getMsgtype() == ForIDedObjMsg)
452         return ((struct s_objid_o *) &type.objid)->id.getCollectionID();
453       else
454             CkAbort("Cannot return ArrayID from msg for non-array entity");
455         /* compiler appeasement, even though this will never be executed */
456       return type.array.arr;
457     }
458     void setArrayMgr(const CkGroupID gid) { CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg);  type.array.arr = gid; }
459     int getArrayMgrIdx(void) const {CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg);  return type.array.arr.idx;}
460     UShort &getsetArrayEp(void) {return epIdx;}
461     UShort &getsetArrayBcastEp(void) {return type.group.arrayEp;}
462 #if CMK_SMP_TRACE_COMMTHREAD
463     UInt &getsetArraySrcPe(void) {return type.array.srcpe;}
464 #else
465     UInt &getsetArraySrcPe(void) {return pe;}
466 #endif
467     UChar &getsetArrayHops(void) { CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg); return type.array.hopCount;}
468     int getArrayIfNotThere(void) { CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg); return type.array.ifNotThere;}
469     void setArrayIfNotThere(int nt) { CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg); type.array.ifNotThere=nt;}
470     int *getsetArrayListenerData(void) {return type.array.listenerData;}
471     CkArrayIndex &getsetArrayIndex(void) 
472         { 
473           CkAssert(getMsgtype() == ForArrayEltMsg || getMsgtype() == ArrayEltInitMsg);
474           return *(CkArrayIndex *)&type.array.index;
475         }
476
477 #if USE_CRITICAL_PATH_HEADER_ARRAY
478  public:
479     /** The information regarding the entry methods that executed along the path to this one.
480         \addtogroup CriticalPathFramework
481     */
482     PathHistoryEnvelope pathHistory;
483 #endif
484
485 };
486
487
488 inline envelope *UsrToEnv(const void *const msg) {
489   return (envelope *)((intptr_t)msg - sizeof(envelope));
490 }
491
492 inline void *EnvToUsr(const envelope *const env) {
493   return (void *)((intptr_t)env + sizeof(envelope));
494 }
495
496 inline envelope *_allocEnv(const int msgtype, const int size=0, const int prio=0) {
497   return envelope::alloc(msgtype,size,prio);
498 }
499
500 inline void *_allocMsg(const int msgtype, const int size, const int prio=0) {
501   return EnvToUsr(envelope::alloc(msgtype,size,prio));
502 }
503
504 inline void _resetEnv(envelope *env) {
505   env->reset();
506 }
507
508 #if CMK_REPLAYSYSTEM
509 inline void setEventID(envelope *env){
510   env->setEvent(++CkpvAccess(envelopeEventID));
511 }
512 #endif
513
514 /** @} */
515
516 extern UChar   _defaultQueueing;
517
518 extern void CkPackMessage(envelope **pEnv);
519 extern void CkUnpackMessage(envelope **pEnv);
520
521 class MsgPool: public SafePool<void *> {
522 private:
523     static void *_alloc(void) {
524       /* CkAllocSysMsg() called in .def.h is not thread of sigio safe */
525       envelope *env = _allocEnv(ForChareMsg,0,0);
526       env->setQueueing(_defaultQueueing);
527       env->setMsgIdx(0);
528       return EnvToUsr(env);
529     }
530     static void _reset(void* m) {
531       envelope *env = UsrToEnv(m);
532       _resetEnv(env);
533     }
534 public:
535     MsgPool():SafePool<void*>(_alloc, CkFreeMsg, _reset) {}
536 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
537         void *get(void){
538             return allocfn();
539         }
540         void put(void *m){
541         }
542 #endif
543 };
544
545 CkpvExtern(MsgPool*, _msgPool);
546
547 #endif