Reference number field: missing middle interface
[charm.git] / src / ck-core / envelope.h
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7 /**
8  @defgroup CkEnvelope
9  \brief  Charm++ message header.
10 */
11 #ifndef _ENVELOPE_H
12 #define _ENVELOPE_H
13
14 #ifndef CkIntbits
15 #define CkIntbits (sizeof(int)*8)
16 #endif
17
18 #if CMK_ERROR_CHECKING
19 #define _SET_USED(env, x) (env)->setUsed((x))
20 #define _CHECK_USED(env) do { if(env->isUsed()) \
21                            CmiAbort("Message being re-sent. Aborting...\n"); \
22                          } while(0)
23 #else
24 #define _SET_USED(env, x) do{}while(0)
25 #define _CHECK_USED(env) do{}while(0)
26 #endif
27
28 #define CkMsgAlignmentMask     (sizeof(double)-1)
29 #define CkMsgAlignLength(x) (((x)+CkMsgAlignmentMask)&(~(CkMsgAlignmentMask)))
30 #define CkMsgAlignOffset(x)     (CkMsgAlignLength(x)-(x))
31 #define CkPriobitsToInts(nBits)    ((nBits+CkIntbits-1)/CkIntbits)
32 // silly ancient name: for backward compatability only.
33 #define PW(x) CkPriobitsToInts(x) 
34
35
36
37 //#define USE_CRITICAL_PATH_HEADER_ARRAY
38
39 /**
40     \addtogroup CriticalPathFramework 
41     @{
42 */
43
44 /** A class that is used to track the entry points and other information 
45     about a critical path as a charm++ program executes.
46
47     This class won't do useful things unless USE_CRITICAL_PATH_HEADER_ARRAY is defined
48 */
49 class PathHistoryEnvelope {
50  protected:
51   // When passing paths forward, store information on PEs, in backward pass, lookup necessary information
52   int sender_history_table_idx;
53   double totalTime;
54  public:
55   double getTotalTime() const{ return totalTime; }
56   int get_sender_history_table_idx() const{ return sender_history_table_idx; }
57   void set_sender_history_table_idx(int i) { sender_history_table_idx = i; }
58   PathHistoryEnvelope(){ 
59 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
60     reset(); 
61 #endif
62   }
63   double getTime() const{ return totalTime; }
64   void setTime(double t){ totalTime = t; }
65   void pup(PUP::er &p) {
66     p | sender_history_table_idx;
67     p | totalTime;
68   } 
69   void reset();
70   void print() const;
71   /// Write a description of the path into the beginning of the provided buffer. The buffer ought to be large enough.
72   void printHTMLToString(char* buf) const{
73     buf[0] = '\0';
74     sprintf(buf+strlen(buf), "Path Time=%lf<br> Sender idx=%d", (double)totalTime, (int)sender_history_table_idx);
75   }
76   /// The number of available EP counts 
77   int getNumUsed() const;
78   /// Return the count value for the idx'th available EP  
79   int getUsedCount(int idx) const;
80   /// Return the idx'th available EP 
81   int getUsedEp(int idx) const;
82   int getEpCount(int ep) const;
83   void incrementTotalTime(double time);
84   //  void createPath(envelope *originatingMsg);
85   void setDebug100();
86 };
87 /** @} */
88
89
90
91 typedef unsigned int   UInt;
92 typedef unsigned short UShort;
93 typedef unsigned char  UChar;
94
95 #include "charm.h" // for CkGroupID, and CkEnvelopeType
96 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
97 #include "ckobjid.h" //for the ckobjId
98 #endif
99
100 /**
101 @addtogroup CkEnvelope
102 */
103
104 CkpvExtern(int, envelopeEventID);
105
106 /**
107 @{
108 The class envelope defines a Charm++ message's header. The first
109 'CmiReservedHeaderSize' bytes of memory is exclusively reserved for Converse
110 header, which is defined in convere.h and platform specific config files.
111
112 After Charm++ envelope comes the payload, i.e. a variable-length amount of user
113 data. Following the user data, optionally, a variable number of bits of
114 priority data can be stored at the end. Function
115 envelope::alloc(msgtype,size,prio) is always used to allocate the whole
116 message. Note that this memory layout must be observed.
117
118 The following are a few terms that are used often:
119
120 <pre>
121  Envelope pointer        \
122  Converse message pointer -> [ [ Converse envelope ]       ]
123                              [       Charm envelope        ] 
124  User message pointer     -> [ User data/payload ... ]
125  Priority pointer         -> [ Priority ints ... ]
126 </pre>
127
128 The "message pointers" passed to and from users bypass the envelope and point
129 *directly* to the user data--the routine "EnvToUsr" below adjusts an envelope
130 (or converse message) pointer into this user message pointer.  There is a
131 corresponding routine "UsrToEnv" which takes the user data pointer and returns
132 a pointer to the envelope/converse message.
133
134 Unfortunately, in the guts of Charm++ it's not always clear whether you've been
135 given a converse or user message pointer, as both tend to be passed as void *.
136 Confusing the two will invariably result in data corruption and bizarre
137 crashes.
138
139 FIXME: Make CkMessage inherit from envelope,
140 which would unify converse, envelope, and 
141 user message pointers.
142 */
143 class envelope {
144   private:
145     /// Converse message envelope, Must be first field in this class
146     char   core[CmiReservedHeaderSize];
147 public:
148  /**
149    This union stores the type-specific message information.
150    Keeping this in a union allows the different kinds of messages 
151    to have different fields/types, in an alignment-safe way, 
152    without wasting any storage.
153  */
154     union u_type {
155       struct s_chare {  // NewChareMsg, NewVChareMsg, ForChareMsg, ForVidMsg, FillVidMsg
156         void *ptr;      ///< object pointer
157         UInt forAnyPe;  ///< Used only by newChare
158       } chare;
159       struct s_group {         // NodeBocInitMsg, BocInitMsg, ForNodeBocMsg, ForBocMsg
160         CkGroupID g;           ///< GroupID
161         CkNodeGroupID rednMgr; ///< Reduction manager for this group (constructor only!)
162         CkGroupID dep;         ///< create after dep is created (constructor only!)
163         int epoch;             ///< "epoch" this group was created during (0--mainchare, 1--later)
164         UShort arrayEp;        ///< Used only for array broadcasts
165       } group;
166       struct s_array{             ///< For arrays only (ArrayEltInitMsg, ForArrayEltMsg)
167         CkArrayIndexStruct index; ///< Array element index
168         int listenerData[CK_ARRAYLISTENER_MAXLEN]; ///< For creation
169         CkGroupID arr;            ///< Array manager GID
170         UChar hopCount;           ///< number of times message has been routed
171         UChar ifNotThere;         ///< what to do if array element is missing
172       } array;
173       struct s_roData {    ///< RODataMsg for readonly data type
174         UInt count;
175       } roData;
176       struct s_roMsg {     ///< ROMsgMsg for readonlys defined in ci files
177         UInt roIdx;
178       } roMsg;
179     };
180     struct s_attribs {  // Packed bitwise struct
181       UChar msgIdx;     ///< Usertype of message (determines pack routine)
182       UChar mtype;      ///< e.g., ForBocMsg
183       UChar queueing:4; ///< Queueing strategy (FIFO, LIFO, PFIFO, ...)
184       UChar isPacked:1; ///< If true, message must be unpacked before use
185       UChar isUsed:1;   ///< Marker bit to prevent message re-send.
186     };
187 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
188     CkObjID sender;
189     CkObjID recver;
190     MCount SN;
191     MCount TN;
192     MlogEntry *localMlogEntry;
193         bool freeMsg;
194 #endif
195 private:
196     u_type type;           ///< Depends on message type (attribs.mtype)
197     CMK_REFNUM_TYPE ref;            ///< Used by futures
198     s_attribs attribs;
199     UChar align[CkMsgAlignOffset(CmiReservedHeaderSize+sizeof(u_type)+sizeof(CMK_REFNUM_TYPE)+sizeof(s_attribs))];    ///< padding to make sure sizeof(double) alignment
200     
201     //This struct should now be sizeof(void*) aligned.
202     UShort priobits;   ///< Number of bits of priority data after user data
203     UShort epIdx;      ///< Entry point to call
204     UInt   pe;         ///< source processor
205     UInt   event;      ///< used by projections
206     UInt   totalsize;  ///< Byte count from envelope start to end of priobits
207     
208   public:
209 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
210     UInt piggyBcastIdx;
211 #endif
212     void pup(PUP::er &p);
213     UInt   getEvent(void) const { return event; }
214     void   setEvent(const UInt e) { event = e; }
215     CMK_REFNUM_TYPE   getRef(void) const { return ref; }
216     void   setRef(const CMK_REFNUM_TYPE r) { ref = r; }
217     UChar  getQueueing(void) const { return attribs.queueing; }
218     void   setQueueing(const UChar q) { attribs.queueing=q; }
219     UChar  getMsgtype(void) const { return attribs.mtype; }
220     void   setMsgtype(const UChar m) { attribs.mtype = m; }
221 #if CMK_ERROR_CHECKING
222     UChar  isUsed(void) { return attribs.isUsed; }
223     void   setUsed(const UChar u) { attribs.isUsed=u; }
224 #else /* CMK_ERROR_CHECKING */
225     inline void setUsed(const UChar u) {}
226 #endif
227     UChar  getMsgIdx(void) const { return attribs.msgIdx; }
228     void   setMsgIdx(const UChar idx) { attribs.msgIdx = idx; }
229     UInt   getTotalsize(void) const { return totalsize; }
230     void   setTotalsize(const UInt s) { totalsize = s; }
231     UInt   getUsersize(void) const { return totalsize - priobits - sizeof(envelope); }
232     UChar  isPacked(void) const { return attribs.isPacked; }
233     void   setPacked(const UChar p) { attribs.isPacked = p; }
234     UShort getPriobits(void) const { return priobits; }
235     void   setPriobits(const UShort p) { priobits = p; }
236     UShort getPrioWords(void) const { return CkPriobitsToInts(priobits); }
237     UShort getPrioBytes(void) const { return getPrioWords()*sizeof(int); }
238     void*  getPrioPtr(void) const { 
239       return (void *)((char *)this + totalsize - getPrioBytes());
240     }
241     static envelope *alloc(const UChar type, const UInt size=0, const UShort prio=0)
242     {
243       CkAssert(type>=NewChareMsg && type<=ForArrayEltMsg);
244       register UInt tsize = sizeof(envelope)+ 
245             CkMsgAlignLength(size)+
246             sizeof(int)*CkPriobitsToInts(prio);
247       register envelope *env = (envelope *)CmiAlloc(tsize);
248 #if CMK_REPLAYSYSTEM
249       //for record-replay
250       memset(env, 0, sizeof(envelope));
251       env->setEvent(++CkpvAccess(envelopeEventID));
252 #endif
253       env->setMsgtype(type);
254       env->totalsize = tsize;
255       env->priobits = prio;
256       env->setPacked(0);
257       env->type.group.dep.setZero();
258       _SET_USED(env, 0);
259       env->setRef(0);
260
261 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
262       env->pathHistory.reset();
263 #endif
264
265 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
266       env->sender.type = TypeInvalid;
267       env->recver.type = TypeInvalid;
268       env->SN = 0;
269       env->TN = 0;
270       env->localMlogEntry = NULL;
271 #endif
272
273       return env;
274     }
275     void reset() {
276       setEvent(++CkpvAccess(envelopeEventID));
277     }
278     UShort getEpIdx(void) const { return epIdx; }
279     void   setEpIdx(const UShort idx) { epIdx = idx; }
280     UInt   getSrcPe(void) const { return pe; }
281     void   setSrcPe(const UInt s) { pe = s; }
282     static void setSrcPe(char *env, const UInt s) { ((envelope*)env)->setSrcPe(s); }
283
284 // Readonly-specific fields
285     UInt   getCount(void) const { 
286       CkAssert(getMsgtype()==RODataMsg); return type.roData.count; 
287     }
288     void   setCount(const UInt c) { 
289       CkAssert(getMsgtype()==RODataMsg); type.roData.count = c; 
290     }
291     UInt   getRoIdx(void) const { 
292       CkAssert(getMsgtype()==ROMsgMsg); return type.roMsg.roIdx; 
293     }
294     void   setRoIdx(const UInt r) { 
295       CkAssert(getMsgtype()==ROMsgMsg); type.roMsg.roIdx = r; 
296     }
297     
298  // Chare-specific fields
299     UInt isForAnyPE(void) { 
300       CkAssert(getMsgtype()==NewChareMsg || getMsgtype()==NewVChareMsg); 
301       return type.chare.forAnyPe; 
302     }
303     void setForAnyPE(UInt f) { 
304       CkAssert(getMsgtype()==NewChareMsg || getMsgtype()==NewVChareMsg); 
305       type.chare.forAnyPe = f; 
306     }
307     void*  getVidPtr(void) const {
308       CkAssert(getMsgtype()==NewVChareMsg || getMsgtype()==ForVidMsg
309           || getMsgtype()==FillVidMsg ||  getMsgtype()==DeleteVidMsg);
310       return type.chare.ptr;
311     }
312     void   setVidPtr(void *p) {
313       CkAssert(getMsgtype()==NewVChareMsg || getMsgtype()==ForVidMsg
314           || getMsgtype()==FillVidMsg ||  getMsgtype()==DeleteVidMsg);
315       type.chare.ptr = p;
316     }
317     void*  getObjPtr(void) const { 
318       CkAssert(getMsgtype()==ForChareMsg); return type.chare.ptr; 
319     }
320     void   setObjPtr(void *p) { 
321       CkAssert(getMsgtype()==ForChareMsg); type.chare.ptr = p; 
322     }
323
324 // Group-specific fields
325     CkGroupID   getGroupNum(void) const {
326       CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
327           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
328       return type.group.g;
329     }
330     void   setGroupNum(const CkGroupID g) {
331       CkAssert(getMsgtype()==BocInitMsg || getMsgtype()==ForBocMsg
332           || getMsgtype()==NodeBocInitMsg || getMsgtype()==ForNodeBocMsg);
333       type.group.g = g;
334     }
335     void setGroupEpoch(int epoch) { type.group.epoch=epoch; }
336     int getGroupEpoch(void) { return type.group.epoch; }
337     void setRednMgr(CkNodeGroupID r){ type.group.rednMgr = r; }
338     CkNodeGroupID getRednMgr(){ return type.group.rednMgr; }
339     CkGroupID getGroupDep(){ return type.group.dep; }
340     void setGroupDep(const CkGroupID &r){ type.group.dep = r; }
341
342 // Array-specific fields
343     CkGroupID &getsetArrayMgr(void) {return type.array.arr;}
344     int getArrayMgrIdx(void) const {return type.array.arr.idx;}
345     UShort &getsetArrayEp(void) {return epIdx;}
346     UShort &getsetArrayBcastEp(void) {return type.group.arrayEp;}
347     UInt &getsetArraySrcPe(void) {return pe;}
348     UChar &getsetArrayHops(void) {return type.array.hopCount;}
349     int getArrayIfNotThere(void) {return type.array.ifNotThere;}
350     void setArrayIfNotThere(int nt) {type.array.ifNotThere=nt;}
351     int *getsetArrayListenerData(void) {return type.array.listenerData;}
352     CkArrayIndexMax &getsetArrayIndex(void) 
353         {return *(CkArrayIndexMax *)&type.array.index;}
354
355 #ifdef USE_CRITICAL_PATH_HEADER_ARRAY
356  public:
357     /** The information regarding the entry methods that executed along the path to this one.
358         \addtogroup CriticalPathFramework
359     */
360     PathHistoryEnvelope pathHistory;
361 #endif
362
363 };
364
365
366 inline envelope *UsrToEnv(const void *const msg) {
367   return (((envelope *) msg)-1);
368 }
369
370 inline void *EnvToUsr(const envelope *const env) {
371   return ((void *)(env+1));
372 }
373
374 inline envelope *_allocEnv(const int msgtype, const int size=0, const int prio=0) {
375   return envelope::alloc(msgtype,size,prio);
376 }
377
378 inline void *_allocMsg(const int msgtype, const int size, const int prio=0) {
379   return EnvToUsr(envelope::alloc(msgtype,size,prio));
380 }
381
382 inline void _resetEnv(envelope *env) {
383   env->reset();
384 }
385
386 inline void setEventID(envelope *env){
387   env->setEvent(++CkpvAccess(envelopeEventID));
388 }
389
390 /** @} */
391
392 extern UChar   _defaultQueueing;
393
394 extern void CkPackMessage(envelope **pEnv);
395 extern void CkUnpackMessage(envelope **pEnv);
396
397 class MsgPool: public SafePool<void *> {
398 private:
399     static void *_alloc(void) {
400       /* CkAllocSysMsg() called in .def.h is not thread of sigio safe */
401       register envelope *env = _allocEnv(ForChareMsg,0,0);
402       env->setQueueing(_defaultQueueing);
403       env->setMsgIdx(0);
404       return EnvToUsr(env);
405     }
406     static void _reset(void* m) {
407       register envelope *env = UsrToEnv(m);
408       _resetEnv(env);
409     }
410 public:
411     MsgPool():SafePool<void*>(_alloc, CkFreeMsg, _reset) {}
412 #if (defined(_FAULT_MLOG_) || defined(_FAULT_CAUSAL_))
413         void *get(void){
414             return allocfn();
415         }
416         void put(void *m){
417         }
418 #endif
419 };
420
421 CkpvExtern(MsgPool*, _msgPool);
422
423 #endif