1b5029376ce26a6f41700025db0f7bc8d206be1a
[charm.git] / src / conv-core / converse.h
1 /**
2   @file
3   @brief Main Converse header file.  Everything in Converse is 
4   either declared here directly, or else included from here.
5
6   Routine names in Converse include a short prefix starting with "C".
7   These generally tell you what category the routine is in:
8   - Cmi, Converse Machine Interface, the machine layer. (machine.c)
9      Also used for various generic low-level features.
10   - Cth, Converse threads, user-level nonpreemptive threads. (threads.c) 
11   - Ccd, Converse condition detection, similar to signal handling. (conv-conds.c)
12   - Ccs, Converse client/server, socket access to parallel job. (conv-ccs.c; ccs-*)
13   - Cpd, Converse parallel debugger. (debug-*)
14   - Crn, Converse random number generation. (random.c)
15   - Csd, Converse scheduler daemon.  (convcore.c)
16   - Cqs, Converse prioritized queueing system. (queueing.c)
17   - CQd, Converse quiesence detection. (quiescense.c)
18      Not the same as Charm++ QD. (qd.C)
19   
20   Globally accessible variables in Converse can be shared as:
21   - Cpv, Converse processor-private variable.  Very common;
22      one copy per processor of each node.
23   - Ctv, Converse thread-private variable.  One copy per Converse thread. 
24   - Csv, Converse node-shared variable.  Global variables 
25      shared by all processors of a node (beware of thread safety!)
26
27   @ingroup CharmScheduler
28   @ingroup ConverseScheduler
29
30 */
31 #ifndef CONVERSE_H
32 #define CONVERSE_H
33
34 #define CMIALIGN(x,n)       (size_t)((~(n-1))&((x)+(n-1)))
35 /*#define ALIGN8(x)        (size_t)((~7)&((x)+7)) */
36 #define ALIGN8(x)          CMIALIGN(x,8)
37
38 /**
39   Grab configuration files generated by build and configure scripts. 
40 */
41 #include "conv-config.h"
42
43 #if CMK_HAS_STDINT_H
44 #include <stdint.h>
45 #endif
46
47 #include <stdio.h>
48 #include <stdlib.h>
49
50 /* Paste the tokens x and y together, without any space between them.
51    The ANSI C way to do this is the bizarre ## "token-pasting" 
52    preprocessor operator.
53  */
54 #define CMK_CONCAT(x,y) x##y
55 /* Tag variable y as being from unit x: */
56 #define CMK_TAG(x,y) x##y##_
57
58 #include "pup_c.h"
59
60 /* the following flags denote properties of the C compiler,  */
61 /* not the C++ compiler.  If this is C++, ignore them.       */
62 #ifdef __cplusplus
63
64 /* Only C++ needs this backup bool defined.  We'll assume that C doesn't
65    use it */
66
67 #if ! CMK_BOOL_DEFINED
68 enum CmiBool {CmiFalse=0, CmiTrue=1};
69 typedef enum {false = 0, true = 1} bool;
70 #else
71 typedef bool CmiBool;
72 #define CmiFalse false
73 #define CmiTrue true
74 #endif
75
76 #if ! CMK_HAS_OFFSETOF
77 #undef offsetof
78 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
79 #else
80 #include <stddef.h>
81 #endif
82
83 extern "C" {
84 #endif
85
86 /* Global variables used by charmdebug to maintain information */
87 extern void CpdSetInitializeMemory(int v);
88 extern void CpdSystemEnter();
89 extern void CpdSystemExit();
90 #if CMK_ERROR_CHECKING
91 extern int memory_status_info;
92 extern int memory_chare_id;
93 #define setMemoryStatus(p) { \
94   int tmp = memory_status_info; \
95   memory_status_info = p; \
96   p = tmp; \
97 }
98 int setMemoryChareIDFromPtr(void *p);
99 void setMemoryChareID(int id);
100 void setMemoryOwnedBy(void *p, int id);
101 #else
102 #define setMemoryStatus(p) /* empty */
103 #define setMemoryChareIDFromPtr(p) /* empty */
104 #define setMemoryChareID(p) /* empty */
105 #define setMemoryOwnedBy(p, id) /* empty */
106 #endif
107
108 /******************************************************************************
109  *
110  * Deal with Shared Memory
111  *
112  * Shared memory strongly affects how CPV, CSV, and CmiMyPe are defined,
113  * and how memory locking is performed. Therefore, we control all these
114  * functions with a single flag.
115  *
116  *****************************************************************************/
117
118 #ifdef __cplusplus
119 /* In C++, use new so t's constructor gets called */
120 # define CpvInit_Alloc(t,n) new t[n]
121 # define CpvInit_Alloc_scalar(t) new t
122 #else
123 # define CpvInit_Alloc(t,n) (t *)calloc(n,sizeof(t))
124 # define CpvInit_Alloc_scalar(t) (t *)calloc(1,sizeof(t))
125 #endif
126
127 extern int CmiMyRank_();
128
129 #if CMK_SHARED_VARS_UNAVAILABLE /* Non-SMP version of shared vars. */
130 extern int _Cmi_mype;
131 extern int _Cmi_numpes;
132 extern int _Cmi_myrank; /* Normally zero; only 1 during SIGIO handling */
133 extern int _Cmi_mynode;
134 extern int _Cmi_numnodes;
135
136 #define CmiMyPe()           _Cmi_mype
137 #define CmiMyRank()         0
138 #define CmiNumPes()         _Cmi_numpes
139 #define CmiMyNodeSize()     1
140 #define CmiMyNode()         _Cmi_mype
141 #define CmiNumNodes()       _Cmi_numpes
142 #define CmiNodeFirst(node)  (node)
143 #define CmiNodeSize(node)   1
144 #define CmiNodeOf(pe)       (pe)
145 #define CmiRankOf(pe)       0
146
147 #define CpvDeclare(t,v) t CMK_TAG(Cpv_,v)[2]
148 #define CpvExtern(t,v)  extern t CMK_TAG(Cpv_,v)[2]
149 #ifdef __cplusplus
150 #define CpvCExtern(t,v)    extern "C" t CMK_TAG(Cpv_,v)[2]
151 #else
152 #define CpvCExtern(t,v)    CpvExtern(t,v)
153 #endif
154 #define CpvStaticDeclare(t,v) static t CMK_TAG(Cpv_,v)[2]
155 #define CpvInitialize(t,v) do {} while(0)
156 #define CpvInitialized(v) 1
157 #define CpvAccess(v) CMK_TAG(Cpv_,v)[_Cmi_myrank]
158 #define CpvAccessOther(v, r) CMK_TAG(Cpv_,v)[r]
159
160 extern void CmiMemLock();
161 extern void CmiMemUnlock();
162 #define CmiNodeBarrier() /*empty*/
163 #define CmiNodeAllBarrier() /*empty*/
164 #define CmiSvAlloc CmiAlloc
165
166 typedef int CmiNodeLock;
167 #define CmiCreateLock() (0)
168 #define CmiLock(lock) {(lock)++;}
169 #define CmiUnlock(lock)  {(lock)--;}
170 #define CmiTryLock(lock)  ((lock)?1:((lock)=1,0))
171 #define CmiDestroyLock(lock) /*empty*/
172
173 #endif
174
175 #if CMK_SHARED_VARS_POSIX_THREADS_SMP /*Used by the net-*-smp versions*/
176
177 #include <pthread.h>
178 #include <sched.h>
179 #ifdef CMK_FAKE_SCHED_YIELD
180 #include <unistd.h>
181 #define sched_yield() sleep(0)
182 #endif
183
184 extern int _Cmi_numpes;
185 extern int _Cmi_mynodesize;
186 extern int _Cmi_mynode;
187 extern int _Cmi_numnodes;
188 extern int _Cmi_noprocforcommthread;
189
190 extern int CmiMyPe();
191 extern int CmiMyRank();
192 #define CmiNumPes()         _Cmi_numpes
193 #define CmiMyNodeSize()     _Cmi_mynodesize
194 #define CmiMyNode()         _Cmi_mynode
195 #define CmiNumNodes()       _Cmi_numnodes
196 extern int CmiNodeFirst(int node);
197 extern int CmiNodeSize(int node);
198 extern int CmiNodeOf(int pe);
199 extern int CmiRankOf(int pe);
200
201 #define CMK_CPV_IS_SMP sched_yield();
202
203 extern void CmiNodeBarrier(void);
204 extern void CmiNodeAllBarrier(void);
205 #define CmiSvAlloc CmiAlloc
206
207 #if CMK_HAS_SPINLOCK && CMK_USE_SPINLOCK
208 typedef pthread_spinlock_t *CmiNodeLock;
209 #define CmiLock(lock) (pthread_spin_lock(lock))
210 #define CmiUnlock(lock) (pthread_spin_unlock(lock))
211 #define CmiTryLock(lock) (pthread_spin_trylock(lock))
212 #else
213 typedef pthread_mutex_t *CmiNodeLock;
214 #define CmiLock(lock) (pthread_mutex_lock(lock))
215 #define CmiUnlock(lock) (pthread_mutex_unlock(lock))
216 #define CmiTryLock(lock) (pthread_mutex_trylock(lock))
217 #endif
218 extern CmiNodeLock CmiCreateLock();
219 extern void CmiDestroyLock(CmiNodeLock lock);
220
221 extern CmiNodeLock CmiMemLock_lock;
222 #define CmiMemLock() do{if (CmiMemLock_lock) CmiLock(CmiMemLock_lock);} while (0)
223
224 #define CmiMemUnlock() do{if (CmiMemLock_lock) CmiUnlock(CmiMemLock_lock);} while (0)
225
226
227 #endif
228
229 #include "string.h"
230
231 #if CMK_BLUEGENEL || CMK_BLUEGENEP
232 #include "cmimemcpy.h"
233 #else
234 #define CmiMemcpy(dest, src, size) memcpy((dest), (src), (size))
235 #endif
236
237 #if CMK_SHARED_VARS_UNIPROCESSOR /*Used only by uth- and sim- versions*/
238
239 extern int _Cmi_mype;
240 extern int _Cmi_numpes;
241
242 #define CmiMyPe()              _Cmi_mype
243 #define CmiMyRank()            _Cmi_mype
244 #define CmiNumPes()            _Cmi_numpes
245 #define CmiMyNodeSize()        _Cmi_numpes
246 #define CmiMyNode()            0
247 #define CmiNumNodes()          1
248 #define CmiNodeFirst(node)     0
249 #define CmiNodeSize(node)      _Cmi_numpes
250 #define CmiNodeOf(pe)          0
251 #define CmiRankOf(pe)          (pe)
252
253 #define CpvDeclare(t,v) t* CMK_TAG(Cpv_,v)
254 #define CpvExtern(t,v)  extern t* CMK_TAG(Cpv_,v)
255 #ifdef __cplusplus
256 #define CpvCExtern(t,v)  extern "C" t* CMK_TAG(Cpv_,v)
257 #else
258 #define CpvCExtern(t,v)    CpvExtern(t,v)
259 #endif
260 #define CpvStaticDeclare(t,v) static t* CMK_TAG(Cpv_,v)
261 #define CpvInitialize(t,v)\
262   do  { if (CMK_TAG(Cpv_,v)==0)\
263         { CMK_TAG(Cpv_,v) = CpvInit_Alloc(t,CmiNumPes()); }}\
264   while(0)
265 #define CpvInitialized(v) (0!=CMK_TAG(Cpv_,v))
266 #define CpvAccess(v) CMK_TAG(Cpv_,v)[CmiMyPe()]
267 #define CpvAccessOther(v, r) CMK_TAG(Cpv_,v)[r]
268
269 #define CmiMemLock() 0
270 #define CmiMemUnlock() 0
271 extern void CmiNodeBarrier();
272 extern void CmiNodeAllBarrier();
273 #define CmiSvAlloc CmiAlloc
274
275 typedef int *CmiNodeLock;
276 extern CmiNodeLock  CmiCreateLock(void);
277 extern void         CmiLock(CmiNodeLock lock);
278 extern void         CmiUnlock(CmiNodeLock lock);
279 extern int          CmiTryLock(CmiNodeLock lock);
280 extern void         CmiDestroyLock(CmiNodeLock lock);
281
282 #endif
283
284 #if CMK_SHARED_VARS_PTHREADS /*Used only by origin-pthreads*/
285
286 #include <pthread.h>
287 #include <sched.h>
288
289 extern int CmiMyPe();
290 extern int _Cmi_numpes;
291
292 #define CmiNumPes()            _Cmi_numpes
293 #define CmiMyRank()            CmiMyPe()
294 #define CmiMyNodeSize()        _Cmi_numpes
295 #define CmiMyNode()            0
296 #define CmiNumNodes()          1
297 #define CmiNodeFirst(node)     0
298 #define CmiNodeSize(node)      _Cmi_numpes
299 #define CmiNodeOf(pe)          0
300 #define CmiRankOf(pe)          (pe)
301
302 #define CMK_CPV_IS_SMP sched_yield();
303
304 extern void CmiMemLock();
305 extern void CmiMemUnlock();
306 extern void CmiNodeBarrier();
307 extern void CmiNodeAllBarrier();
308 #define CmiSvAlloc CmiAlloc
309
310 typedef pthread_mutex_t *CmiNodeLock;
311 extern CmiNodeLock  CmiCreateLock(void);
312 extern void         CmiLock(CmiNodeLock lock);
313 extern void         CmiUnlock(CmiNodeLock lock);
314 extern int          CmiTryLock(CmiNodeLock lock);
315 extern void         CmiDestroyLock(CmiNodeLock lock);
316
317 #endif
318
319 #if CMK_SHARED_VARS_NT_THREADS /*Used only by win32 versions*/
320
321 #include <windows.h>
322
323 extern int _Cmi_numpes;
324 extern int _Cmi_mynodesize;
325 extern int _Cmi_mynode;
326 extern int _Cmi_numnodes;
327 extern int _Cmi_noprocforcommthread;
328
329 extern int CmiMyPe();
330 extern int CmiMyRank();
331 #define CmiNumPes()         _Cmi_numpes
332 #define CmiMyNodeSize()     _Cmi_mynodesize
333 #define CmiMyNode()         _Cmi_mynode
334 #define CmiNumNodes()       _Cmi_numnodes
335 extern int CmiNodeFirst(int node);
336 extern int CmiNodeSize(int node);
337 extern int CmiNodeOf(int pe);
338 extern int CmiRankOf(int pe);
339
340 #define CMK_CPV_IS_SMP Sleep(0);
341
342 extern void CmiNodeBarrier(void);
343 extern void CmiNodeAllBarrier(void);
344 #define CmiSvAlloc CmiAlloc
345
346 typedef HANDLE CmiNodeLock;
347 extern  CmiNodeLock CmiCreateLock(void);
348 #define CmiLock(lock) (WaitForSingleObject(lock, INFINITE))
349 #define CmiUnlock(lock) (ReleaseMutex(lock))
350 #define CmiTryLock(lock) (WaitForSingleObject(lock, 0))
351 extern  void CmiDestroyLock(CmiNodeLock lock);
352
353 extern CmiNodeLock CmiMemLock_lock;
354 #define CmiMemLock() do{if (CmiMemLock_lock) CmiLock(CmiMemLock_lock);} while (0)
355 #define CmiMemUnlock() do{if (CmiMemLock_lock) CmiUnlock(CmiMemLock_lock);} while (0)
356
357 #endif
358
359 #if CMK_SHARED_VARS_UNAVAILABLE   /* non-SMP version */
360
361 typedef int CmiImmediateLockType;
362 extern int _immediateLock;
363 extern int _immediateFlag;
364 #define CmiCreateImmediateLock() (0)
365 #define CmiImmediateLock(ignored) { _immediateLock++; }
366 #if CMK_IMMEDIATE_MSG
367 #define CmiImmediateUnlock(ignored) \
368   { _immediateLock--; \
369     if(_immediateFlag) \
370       CmiProbeImmediateMsg(); } 
371 #else
372 #define CmiImmediateUnlock(ignored) { _immediateLock--; }
373 #endif
374 #define CmiCheckImmediateLock(ignored) \
375   ((_immediateLock)?((_immediateFlag=1),1):0)
376 #define CmiClearImmediateFlag() { _immediateFlag=0; }
377
378 #else /* SMP and all other weird versions */
379
380 typedef CmiNodeLock CmiImmediateLockType;
381 #define CmiCreateImmediateLock() CmiCreateLock()
382 #define CmiImmediateLock(immediateLock) CmiLock((immediateLock))
383 #define CmiImmediateUnlock(immediateLock) CmiUnlock((immediateLock)) 
384 #define CmiCheckImmediateLock(ignored)  (0)
385 #define CmiClearImmediateFlag() 
386
387 #endif
388
389 /* This is the default Cpv implmentation for SMP-style systems:
390 A Cpv variable is actually a pointer to an array of values, one
391 for each processor in the node.
392 */
393 #ifdef CMK_CPV_IS_SMP
394
395 /* buggy xlc compiler on bluegene/p does not like memory fence in Cpvs */
396 #if CMK_BLUEGENEP && ( defined(__xlC__) || defined(__xlc__) )
397 #define CpvMemoryReadFence()
398 #define CpvMemoryWriteFence()
399 #else
400 #define CpvMemoryReadFence() CmiMemoryReadFence()
401 #define CpvMemoryWriteFence() CmiMemoryWriteFence()
402 #endif
403
404 #if CMK_HAS_TLS_VARIABLES && !CMK_NOT_USE_TLS_THREAD
405 #define CpvDeclare(t,v) __thread t* CMK_TAG(Cpv_,v) = NULL;   \
406                         int CMK_TAG(Cpv_inited_,v) = 0;  \
407                         t ** CMK_TAG(Cpv_addr_,v);
408 #define CpvExtern(t,v)  extern __thread t* CMK_TAG(Cpv_,v);  \
409                         extern int CMK_TAG(Cpv_inited_,v);  \
410                         extern t ** CMK_TAG(Cpv_addr_,v)
411 #ifdef __cplusplus
412 #define CpvCExtern(t,v) extern "C"  __thread t* CMK_TAG(Cpv_,v);  \
413                         extern "C" int CMK_TAG(Cpv_inited_,v);  \
414                         extern "C" t ** CMK_TAG(Cpv_addr_,v)
415 #else
416 #define CpvCExtern(t,v)    CpvExtern(t,v)
417 #endif
418 #define CpvStaticDeclare(t,v) static __thread t* CMK_TAG(Cpv_,v) = NULL;   \
419                         static int CMK_TAG(Cpv_inited_,v) = 0;  \
420                         static t ** CMK_TAG(Cpv_addr_,v)
421 #define CpvInitialize(t,v)\
422     do { \
423        if (CmiMyRank()) { \
424                /*while (!CpvInitialized(v)) CMK_CPV_IS_SMP;*/\
425                CpvMemoryReadFence(); \
426                while (CMK_TAG(Cpv_inited_,v)==0) { CMK_CPV_IS_SMP; CpvMemoryReadFence(); } \
427                CMK_TAG(Cpv_,v)=CpvInit_Alloc_scalar(t); \
428                CMK_TAG(Cpv_addr_,v)[CmiMyRank()] = CMK_TAG(Cpv_,v); \
429        } else { \
430                CMK_TAG(Cpv_,v)=CpvInit_Alloc_scalar(t); \
431                CMK_TAG(Cpv_addr_,v)=CpvInit_Alloc(t*, 1+CmiMyNodeSize()); \
432                CMK_TAG(Cpv_addr_,v)[CmiMyRank()] = CMK_TAG(Cpv_,v); \
433                CpvMemoryWriteFence();   \
434                CMK_TAG(Cpv_inited_,v)=1; \
435        } \
436     } while(0)
437 #define CpvInitialized(v) (0!=CMK_TAG(Cpv_,v))
438 #define CpvAccess(v) (*CMK_TAG(Cpv_,v))
439 #define CpvAccessOther(v, r) (*(CMK_TAG(Cpv_addr_,v)[r]))
440
441 #else
442
443 #define CpvDeclare(t,v) t* CMK_TAG(Cpv_,v)
444 #define CpvExtern(t,v)  extern t* CMK_TAG(Cpv_,v)
445 #ifdef __cplusplus
446 #define CpvCExtern(t,v)    extern "C" t* CMK_TAG(Cpv_,v)
447 #else
448 #define CpvCExtern(t,v)    CpvExtern(t,v)
449 #endif
450 #define CpvStaticDeclare(t,v) static t* CMK_TAG(Cpv_,v)
451 #define CpvInitialize(t,v)\
452     do { \
453        if (CmiMyRank()) { \
454                CpvMemoryReadFence(); \
455                        while (!CpvInitialized(v)) { CMK_CPV_IS_SMP ; CpvMemoryReadFence(); } \
456        } else { \
457                t* tmp = CpvInit_Alloc(t,1+CmiMyNodeSize());\
458                CpvMemoryWriteFence();   \
459                CMK_TAG(Cpv_,v)=tmp;   \
460                /* CMK_TAG(Cpv_,v)=CpvInit_Alloc(t,1+CmiMyNodeSize()); */\
461        } \
462     } while(0)
463 #define CpvInitialized(v) (0!=CMK_TAG(Cpv_,v))
464 #define CpvAccess(v) CMK_TAG(Cpv_,v)[CmiMyRank()]
465 #define CpvAccessOther(v, r) CMK_TAG(Cpv_,v)[r]
466 #endif
467
468 #endif
469
470 /*Csv are the same almost everywhere:*/
471 #ifndef CsvDeclare
472 #define CsvDeclare(t,v) t CMK_TAG(Csv_,v)
473 #define CsvStaticDeclare(t,v) static t CMK_TAG(Csv_,v)
474 #define CsvExtern(t,v) extern t CMK_TAG(Csv_,v)
475 #define CsvInitialize(t,v) do{}while(0)
476 #define CsvAccess(v) CMK_TAG(Csv_,v)
477 #endif
478
479 extern CmiNodeLock _smp_mutex;
480
481 extern int CmiBarrier(void);
482 extern int CmiBarrierZero(void);
483
484 /* cpu topology */
485 extern int CmiNumCores(void);
486 extern int CmiCpuTopologyEnabled();
487 extern int CmiPeOnSamePhysicalNode(int pe1, int pe2);
488 extern int CmiNumPhysicalNodes();
489 extern int CmiPhysicalNodeID(int pe);
490 extern int CmiNumPesOnPhysicalNode(int node);
491 extern void CmiGetPesOnPhysicalNode(int node, int **pelist, int *num);
492 extern int CmiGetFirstPeOnPhysicalNode(int node);
493 extern int CmiPhysicalRank(int pe);
494
495 extern int CmiPrintCPUAffinity();
496 extern int CmiSetCPUAffinity(int core);
497 extern int CmiOnCore();
498
499 /** Return 1 if our outgoing message queue 
500    for this node is longer than this many bytes. */
501 int CmiLongSendQueue(int forNode,int longerThanBytes);
502
503 /******** CMI: TYPE DEFINITIONS ********/
504
505 typedef CMK_TYPEDEF_INT2      CmiInt2;
506 typedef CMK_TYPEDEF_INT4      CmiInt4;
507 typedef CMK_TYPEDEF_INT8      CmiInt8;
508 typedef CMK_TYPEDEF_UINT2     CmiUInt2;
509 typedef CMK_TYPEDEF_UINT4     CmiUInt4;
510 typedef CMK_TYPEDEF_UINT8     CmiUInt8;
511 typedef CMK_TYPEDEF_FLOAT4    CmiFloat4;
512 typedef CMK_TYPEDEF_FLOAT8    CmiFloat8;
513
514 #if CMK_SIZET_64BIT
515 typedef CmiUInt8     CmiIntPtr;
516 #else
517 typedef CmiUInt4     CmiIntPtr;
518 #endif
519
520
521 typedef void  *CmiCommHandle;
522 typedef void (*CmiHandler)(void *msg);
523 typedef void (*CmiHandlerEx)(void *msg,void *userPtr);
524
525 typedef struct CMK_MSG_HEADER_BASIC CmiMsgHeaderBasic;
526 typedef struct CMK_MSG_HEADER_EXT   CmiMsgHeaderExt;
527
528 #define CmiMsgHeaderSizeBytes (sizeof(CmiMsgHeaderBasic))
529 #define CmiExtHeaderSizeBytes (sizeof(CmiMsgHeaderExt))
530
531 /* all common extra fields in BigSim message header */
532 #define CMK_BIGSIM_FIELDS  CmiInt4 nd,n; double rt; CmiInt2 tID, hID; char t, flag; CmiInt2 ref; CmiInt4 msgID, srcPe;
533
534 #ifndef CmiReservedHeaderSize
535 typedef struct CMK_MSG_HEADER_BIGSIM_   CmiBlueGeneMsgHeader;
536 #define CmiBlueGeneMsgHeaderSizeBytes (sizeof(CmiBlueGeneMsgHeader))
537 #if CMK_BIGSIM_CHARM
538 #  define CmiReservedHeaderSize   CmiBlueGeneMsgHeaderSizeBytes
539 #else
540 #  define CmiReservedHeaderSize   CmiExtHeaderSizeBytes
541 #endif
542 #endif
543
544 /******** CMI, CSD: MANY LOW-LEVEL OPERATIONS ********/
545
546 typedef struct {
547         CmiHandlerEx hdlr;
548         void *userPtr;
549 } CmiHandlerInfo;
550
551 CpvExtern(CmiHandlerInfo*, CmiHandlerTable);
552 CpvExtern(int,         CmiHandlerMax);
553 CpvExtern(void*,       CsdSchedQueue);
554 #if CMK_GRID_QUEUE_AVAILABLE
555 CpvExtern(void *,      CsdGridQueue);
556 #endif
557 #if CMK_OBJECT_QUEUE_AVAILABLE
558 CpvExtern(void*,       CsdObjQueue);
559 #endif
560 #if CMK_NODE_QUEUE_AVAILABLE
561 CsvExtern(void*,       CsdNodeQueue);
562 CsvExtern(CmiNodeLock, CsdNodeQueueLock);
563 #endif
564 CpvExtern(int,         CsdStopFlag);
565 CpvExtern(int,         CsdLocalCount);
566 #define CSD_LOCAL_MAX_DEFAULT 0
567
568 extern int CmiRegisterHandler(CmiHandler h);
569 extern int CmiRegisterHandlerEx(CmiHandlerEx h,void *userPtr);
570 #if CMI_LOCAL_GLOBAL_AVAILABLE
571 extern int CmiRegisterHandlerLocal(CmiHandler);
572 extern int CmiRegisterHandlerGlobal(CmiHandler);
573 #endif
574 extern void CmiNumberHandler(int n, CmiHandler h);
575 extern void CmiNumberHandlerEx(int n, CmiHandlerEx h,void *userPtr);
576
577 #define CmiGetHandler(m)  (((CmiMsgHeaderExt*)m)->hdl)
578 #define CmiGetXHandler(m) (((CmiMsgHeaderExt*)m)->xhdl)
579 #define CmiGetInfo(m)     (((CmiMsgHeaderExt*)m)->info)
580 #define CmiGetRoot(m)     (((CmiMsgHeaderExt*)m)->root)
581 #define CmiGetRedID(m)    (((CmiMsgHeaderExt*)m)->redID)
582 #define CmiGetStrategy(m) (((CmiMsgHeaderExt*)m)->stratid)
583
584 #define CmiSetHandler(m,v)  do {((((CmiMsgHeaderExt*)m)->hdl)=(v));} while(0)
585 #define CmiSetXHandler(m,v) do {((((CmiMsgHeaderExt*)m)->xhdl)=(v));} while(0)
586 #define CmiSetInfo(m,v)     do {((((CmiMsgHeaderExt*)m)->info)=(v));} while(0)
587 #define CmiSetRoot(m,v)     do {((((CmiMsgHeaderExt*)m)->root)=(v));} while(0)
588 #define CmiSetRedID(m,v)    do {((((CmiMsgHeaderExt*)m)->redID)=(v));} while(0)
589 #define CmiSetStrategy(m,v) do {((((CmiMsgHeaderExt*)m)->stratid)=(v);} while(0)
590
591 #define CmiHandlerToInfo(n) (CpvAccess(CmiHandlerTable)[n])
592 #define CmiHandlerToFunction(n) (CmiHandlerToInfo(n).hdlr)
593 #define CmiGetHandlerInfo(env) (CmiHandlerToInfo(CmiGetHandler(env)))
594 #define CmiGetHandlerFunction(env) (CmiHandlerToFunction(CmiGetHandler(env)))
595
596 #if __FAULT__
597 CpvExtern(int, _curRestartPhase);      /* number of restarts */
598 #endif
599
600 #if CMK_MEM_CHECKPOINT
601 #undef CmiSetHandler
602 #define CmiSetHandler(m,v)  do {(((CmiMsgHeaderExt*)m)->hdl)=(v); (((CmiMsgHeaderExt*)m)->pn)=CpvAccess(_curRestartPhase);} while(0)
603 #define MESSAGE_PHASE_CHECK(msg)        \
604         {       \
605           int phase = CmiGetRestartPhase(msg);  \
606           if (phase != 9999 && phase < CpvAccess(_curRestartPhase)) {   \
607             /* CmiPrintf("[%d] discard message of phase %d cur_restart_phase:%d. \n", CmiMyPe(), phase, cur_restart_phase); */  \
608             CmiFree(msg);       \
609             return;     \
610           }     \
611           /* CmiAssert(phase == cur_restart_phase || phase == 9999); */ \
612           if (phase > CpvAccess(_curRestartPhase) && phase != 9999) {    \
613             /* CmiPrintf("[%d] enqueue message of phase %d cur_restart_phase:%d. \n", CmiMyPe(), phase, cur_restart_phase); */  \
614             CsdEnqueueFifo(msg);    \
615             return;     \
616           }     \
617         }
618 #else
619 #define MESSAGE_PHASE_CHECK(msg)
620 #endif
621
622 /** This header goes before each chunk of memory allocated with CmiAlloc. 
623     See the comment in convcore.c for details on the fields.
624 */
625 typedef struct {
626   int size;
627   int ref;
628 } CmiChunkHeader;
629
630 #if CMK_USE_IBVERBS | CMK_USE_IBUD
631 struct infiCmiChunkMetaDataStruct;
632
633 typedef struct infiCmiChunkHeaderStruct{
634   struct infiCmiChunkMetaDataStruct *metaData;
635         CmiChunkHeader chunkHeader;
636 } infiCmiChunkHeader;
637
638 struct infiCmiChunkMetaDataStruct *registerMultiSendMesg(char *msg,int msgSize);
639 #endif
640
641 /* Given a user chunk m, extract the enclosing chunk header fields: */
642 #define SIZEFIELD(m) (((CmiChunkHeader *)(m))[-1].size)
643 #define REFFIELD(m) (((CmiChunkHeader *)(m))[-1].ref)
644 #define BLKSTART(m) (((CmiChunkHeader *)(m))-1)
645
646 extern void* malloc_nomigrate(size_t size);
647
648 /**
649    Allocate `size` bytes of memory usable as a message buffer.
650
651    Such memory may be in limited supply and expensive to obtain on
652    machine layers that use registered or pinned memory when
653    interacting with the communication hardware. Uses besides buffers
654    in which to construct messages should prefer the malloc()/free()
655    provided by libmemory-*.
656 */
657 void    *CmiAlloc(int size);
658 void     CmiReference(void *blk);
659 int      CmiGetReference(void *blk);
660 int      CmiSize(void *blk);
661 void     CmiFree(void *blk);
662
663 #ifndef CMI_TMP_SKIP
664 void *CmiTmpAlloc(int size);
665 void CmiTmpFree(void *);
666 #endif
667
668 /* Pool features */
669
670
671 /* Various special features of certain -memory modes: */
672 extern void * memory_stack_top; /* contains the top of the stack, for -memory charmdebug */
673 void CmiMemoryCheck(void); /* heap check, for -memory paranoid */
674 void CmiMemoryMark(void); /* ignore current allocations, for -memory leak */
675 void CmiMemoryMarkBlock(void *blk); /* ignore this allocation, for -memory leak */
676 void CmiMemorySweep(const char *where); /* print current allocations, for -memory leak */
677 CMK_TYPEDEF_UINT8 CmiMemoryUsage();
678 CMK_TYPEDEF_UINT8 CmiMaxMemoryUsage();
679 void CmiResetMaxMemory();
680 CMK_TYPEDEF_UINT8 CmiMinMemoryUsage();
681 void CmiResetMinMemory();
682
683 /* General functions for malloc'ing aligned buffers */
684 #define CmiRoundUpToPow2(s, p2)  (s + ((p2 - (s & (p2 - 1))) & (p2 - 1)))
685 void* CmiMallocAligned(const size_t size, const unsigned int alignment);
686 void CmiFreeAligned(void* ptr);
687
688 #define CMI_MEMORY_IS_ISOMALLOC   (1<<1)
689 #define CMI_MEMORY_IS_PARANOID    (1<<2)
690 #define CMI_MEMORY_IS_GNU         (1<<3)
691 #define CMI_MEMORY_IS_GNUOLD      (1<<4)
692 #define CMI_MEMORY_IS_OS          (1<<5)
693 #define CMI_MEMORY_IS_CHARMDEBUG  (1<<6)
694 int CmiMemoryIs(int flag); /* return state of this flag */
695
696 #define CMI_THREAD_IS_QT         (1<<1)
697 #define CMI_THREAD_IS_CONTEXT    (1<<2)
698 #define CMI_THREAD_IS_UJCONTEXT  (1<<3)
699 #define CMI_THREAD_IS_PTHREADS   (1<<4)
700 #define CMI_THREAD_IS_FIBERS     (1<<5)
701 #define CMI_THREAD_IS_ALIAS      (1<<6)
702 #define CMI_THREAD_IS_STACKCOPY  (1<<7)
703 #define CMI_THREAD_IS_TLS        (1<<8)
704 int CmiThreadIs(int flag); /* return state of this flag */
705
706 void CmiMkdir(const char *dirName);
707
708 double   CmiCpuTimer(void);
709
710 #if CMK_TIMER_USE_RDTSC 
711 #ifndef __x86_64__
712 # if ! (CMK_GCC_X86_ASM || CMK_GCC_IA64_ASM)
713 /* Can't use rdtsc unless we have x86 or ia64 assembly: */
714 #  undef CMK_TIMER_USE_RDTSC
715 #  undef CMK_TIMER_USE_GETRUSAGE
716 #  define CMK_TIMER_USE_RDTSC 0
717 #  define CMK_TIMER_USE_GETRUSAGE 1
718 # endif
719 #endif
720 #endif
721
722 #if CMK_TIMER_USE_RDTSC 
723 extern double _cpu_speed_factor;
724
725 static __inline__ unsigned long long int rdtsc(void)
726 {
727         unsigned long long int x;
728 #ifdef __x86_64__
729         /* taken from papi code ("perfctr-p3.c") for machines like opteron */
730         do {
731           unsigned int a,d;
732           asm volatile("rdtsc" : "=a" (a), "=d" (d));
733           (x) = ((unsigned long)a) | (((unsigned long)d)<<32);
734         } while(0);
735 #elif CMK_GCC_IA64_ASM
736         __asm__ __volatile__("mov %0=ar.itc" : "=r"(x) :: "memory");
737 #elif CMK_GCC_X86_ASM
738         __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
739 #else
740 #  error "Unknown assembly format-- can't use CMK_TIMER_USE_RDTSC."
741 #endif
742         return x;
743 }
744
745 #define CmiWallTimer() ((double)rdtsc()*(_cpu_speed_factor))
746 #define CmiTimer CmiCpuTimer
747 double   CmiStartTimer(void);
748 double   CmiInitTime(void);
749 #define CmiTimerIsSynchronized()        (0)
750 #define CmiTimerAbsolute()              (0)
751
752 #else
753 void     CmiTimerInit(char **argv);
754 int      CmiTimerAbsolute();
755 double   CmiStartTimer(void);
756 double   CmiInitTime(void);
757 double   CmiTimer(void);
758 double   CmiWallTimer(void);
759 int      CmiTimerIsSynchronized();
760 #endif
761
762 char *CmiPrintDate();
763
764 #include "queueing.h" /* for "Queue" */
765
766 #if CMK_NODE_QUEUE_AVAILABLE
767
768 #define CsdNodeEnqueueGeneral(x,s,i,p) do { \
769           CmiLock(CsvAccess(CsdNodeQueueLock));\
770           CqsEnqueueGeneral((Queue)CsvAccess(CsdNodeQueue),(x),(s),(i),(p)); \
771           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
772         } while(0)
773 #define CsdNodeEnqueueFifo(x)     do { \
774           CmiLock(CsvAccess(CsdNodeQueueLock));\
775           CqsEnqueueFifo((Queue)CsvAccess(CsdNodeQueue),(x)); \
776           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
777         } while(0)
778 #define CsdNodeEnqueueLifo(x)     do { \
779           CmiLock(CsvAccess(CsdNodeQueueLock));\
780           CqsEnqueueLifo((Queue)CsvAccess(CsdNodeQueue),(x))); \
781           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
782         } while(0)
783 #define CsdNodeEnqueue(x)     do { \
784           CmiLock(CsvAccess(CsdNodeQueueLock));\
785           CqsEnqueueFifo((Queue)CsvAccess(CsdNodeQueue),(x));\
786           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
787         } while(0)
788
789 #define CsdNodeEmpty()            (CqsEmpty(C(Queue)pvAccess(CsdNodeQueue)))
790 #define CsdNodeLength()           (CqsLength((Queue)CpvAccess(CsdNodeQueue)))
791
792 #else
793
794 #define CsdNodeEnqueueGeneral(x,s,i,p) (CsdEnqueueGeneral(x,s,i,p))
795 #define CsdNodeEnqueueFifo(x) (CqsEnqueueFifo((Queue)CpvAccess(CsdSchedQueue),(x)))
796 #define CsdNodeEnqueueLifo(x) (CqsEnqueueLifo((Queue)CpvAccess(CsdSchedQueue),(x)))
797 #define CsdNodeEnqueue(x)     (CsdEnqueue(x))
798 #define CsdNodeEmpty()        (CqsEmpty((Queue)CpvAccess(CsdSchedQueue)))
799 #define CsdNodeLength()       (CqsLength((Queue)CpvAccess(CsdSchedQueue)))
800
801 #endif
802
803 #define CsdEnqueueGeneral(x,s,i,p)\
804     (CqsEnqueueGeneral((Queue)CpvAccess(CsdSchedQueue),(x),(s),(i),(p)))
805 #define CsdEnqueueFifo(x)     (CqsEnqueueFifo((Queue)CpvAccess(CsdSchedQueue),(x)))
806 #define CsdEnqueueLifo(x)     (CqsEnqueueLifo((Queue)CpvAccess(CsdSchedQueue),(x)))
807 #define CsdEnqueue(x)         (CqsEnqueueFifo((Queue)CpvAccess(CsdSchedQueue),(x)))
808 #define CsdEmpty()            (CqsEmpty((Queue)CpvAccess(CsdSchedQueue)))
809 #define CsdLength()           (CqsLength((Queue)CpvAccess(CsdSchedQueue)))
810
811 #if CMK_CMIPRINTF_IS_A_BUILTIN /* these are implemented in machine.c */
812 void  CmiPrintf(const char *, ...);
813 void  CmiError(const char *, ...);
814 int   CmiScanf(const char *, ...);
815 /* CmiFlush is disabled in this case */
816 #define CmiFlush(stream) 
817
818 #else /* standard definitions */
819
820 #include <stdio.h>
821
822 /*
823  * I made vprintf functions for CmiPrintf and CmiError, but on the
824  * O2K, there is no equivalent vscanf!
825
826  #define CmiPrintf printf
827  #define CmiError  printf
828 */
829 #include <stdarg.h>
830
831 void  CmiPrintf(const char *format, ...);
832 void  CmiError(const char *format, ...);
833 /* CmiFlush works only when CMK_CMIPRINTF_IS_A_BUILTIN is false */
834 #define CmiFlush(stream)  fflush(stream);
835 #define CmiScanf  scanf
836
837 #endif
838
839 #if defined(__STDC__) || defined(__cplusplus)
840 #define __CMK_STRING(x) #x
841 #else
842 #define __CMK_STRING(x) "x"
843 #endif
844
845 #if ! CMK_ERROR_CHECKING
846 #define CmiAssert(expr) ((void) 0)
847 #else
848 extern void __cmi_assert(const char *, const char *, int);
849 #define CmiAssert(expr) \
850   ((void) ((expr) ? 0 :                   \
851      (__cmi_assert (__CMK_STRING(expr), __FILE__, __LINE__), 0)))
852 #endif
853
854 typedef void (*CmiStartFn)(int argc, char **argv);
855
856 /********* CSD - THE SCHEDULER ********
857   @addtogroup ConverseScheduler
858   @{
859 */
860 CpvExtern(int, _ccd_numchecks);
861 extern void  CcdCallBacks();
862 #define CsdPeriodic() do{ if (CpvAccess(_ccd_numchecks)-- <= 0) CcdCallBacks(); } while(0)
863 #define CsdResetPeriodic()    CpvAccess(_ccd_numchecks) = 0;
864
865 extern void  CsdEndIdle(void);
866 extern void  CsdStillIdle(void);
867 extern void  CsdBeginIdle(void);
868
869 typedef struct {
870   void *localQ;
871   void *nodeQ;
872   void *schedQ;
873   int *localCounter;
874 #if CMK_OBJECT_QUEUE_AVAILABLE
875   void *objQ;
876 #endif
877   CmiNodeLock nodeLock;
878 #if CMK_GRID_QUEUE_AVAILABLE
879   void *gridQ;
880 #endif
881 } CsdSchedulerState_t;
882 extern void CsdSchedulerState_new(CsdSchedulerState_t *state);
883 extern void *CsdNextMessage(CsdSchedulerState_t *state);
884 extern void *CsdNextLocalNodeMessage(CsdSchedulerState_t *state);
885
886 extern void  *CmiGetNonLocal(void);
887 extern void   CmiNotifyIdle(void);
888
889 /*Different kinds of schedulers: generic, eternal, counting, polling*/
890 extern  int CsdScheduler(int maxmsgs);
891 extern void CsdScheduleForever(void);
892 extern  int CsdScheduleCount(int maxmsgs);
893 extern void CsdSchedulePoll(void);
894 extern void CsdScheduleNodePoll(void);
895
896 #define CsdExitScheduler()  (CpvAccess(CsdStopFlag)++)
897 /** @} */
898
899 #if CMK_SPANTREE_USE_COMMON_CODE
900
901 #define CST_W  (CMK_SPANTREE_MAXSPAN)
902 #define CST_NN (CmiNumNodes())
903 #define CmiNodeSpanTreeParent(n) ((n)?(((n)-1)/CST_W):(-1))
904 #define CmiNodeSpanTreeChildren(n,c) do {\
905           int _i; \
906           for(_i=0; _i<CST_W; _i++) { \
907             int _x = (n)*CST_W+_i+1; \
908             if(_x<CST_NN) (c)[_i]=_x; \
909           }\
910         } while(0)
911 #define CmiNumNodeSpanTreeChildren(n) ((((n)+1)*CST_W<CST_NN)? CST_W : \
912           ((((n)*CST_W+1)>=CST_NN)?0:((CST_NN-1)-(n)*CST_W)))
913 #define CST_R(p) (CmiRankOf(p))
914 #define CST_NF(n) (CmiNodeFirst(n))
915 #define CST_SP(n) (CmiNodeSpanTreeParent(n))
916 #define CST_ND(p) (CmiNodeOf(p))
917 #define CST_NS(p) (CmiNodeSize(CST_ND(p)))
918 #define CmiSpanTreeParent(p) ((p)?(CST_R(p)?(CST_NF(CST_ND(p))+(CST_R(p)-1)/CST_W):CST_NF(CST_SP(CST_ND(p)))):(-1))
919 #define CST_C(p) (((CST_R(p)+1)*CST_W<CST_NS(p))?CST_W:(((CST_R(p)*CST_W+1)>=CST_NS(p))?0:((CST_NS(p)-1)-CST_R(p)*CST_W)))
920 #define CST_SC(p) (CmiNumNodeSpanTreeChildren(CST_ND(p)))
921 #define CmiNumSpanTreeChildren(p) (CST_R(p)?CST_C(p):(CST_SC(p)+CST_C(p)))
922 #define CmiSpanTreeChildren(p,c) do {\
923           int _i,_c=0; \
924           if(CST_R(p)==0) { \
925             for(_i=0;_i<CST_W;_i++) { \
926               int _x = CST_ND(p)*CST_W+_i+1; \
927               if(_x<CST_NN) (c)[_c++]=CST_NF(_x); \
928             }\
929           } \
930           for(_i=0;_i<CST_W;_i++) { \
931             int _x = CST_R(p)*CST_W+_i+1; \
932             if(_x<CST_NS(p)) (c)[_c++]=CST_NF(CST_ND(p))+_x; \
933           }\
934         } while(0)
935
936 #else
937
938 int      CmiNumSpanTreeChildren(int) ;
939 int      CmiSpanTreeParent(int) ;
940 void     CmiSpanTreeChildren(int node, int *children);
941 int      CmiNumNodeSpanTreeChildren(int);
942 int      CmiNodeSpanTreeParent(int) ;
943 void     CmiNodeSpanTreeChildren(int node, int *children) ;
944 #endif
945
946 /****** MULTICAST GROUPS ******/
947
948 typedef CMK_MULTICAST_GROUP_TYPE CmiGroup;
949
950 void     CmiGroupInit();
951 CmiGroup CmiEstablishGroup(int npes, int *pes);
952 void     CmiLookupGroup(CmiGroup grp, int *npes, int **pes);
953
954 /****** CMI MESSAGE TRANSMISSION ******/
955
956 /* Utility function: it packs a multiple chunk message into a singly one.
957  * Receives the two return values outsize and outdata to return the size of the
958  * composed message and the message itself. It receives the number of chunks to
959  * compact, their sizes and datas. The types of the parameters are:
960  *
961  * int outsize, inndata, insizes;
962  * char *outdata;
963  * char **indatas;
964  *
965  * If inndata is negative, it means that the messages need to be copied together
966  * with their memory header at the beginning (message nesting), and padded to 8
967  * bytes. The first message never has its memory header attached (it uses the
968  * one of the new message).
969  */
970
971 #define VECTOR_COMPACT(outsize,outdata,inndata,insizes,indatas,chunkHeaderSize) {\
972   int i;\
973   char *tmp;\
974   outsize=0;\
975   if (inndata>=0) for(i=0; i<inndata; ++i) outsize += insizes[i];\
976   else {\
977     for(i=0; i<-inndata; ++i) outsize += ALIGN8(insizes[i]);\
978     outsize -= (inndata+1) * chunkHeaderSize;\
979   }\
980   outdata = (char *)CmiAlloc(outsize);\
981   if (!outdata) fprintf(stderr, "%d: Out of mem\n", CmiMyNode());\
982   tmp = outdata;\
983   if (inndata>=0) {\
984     for (i=0; i<inndata; ++i) {\
985       memcpy(tmp, indatas[i], insizes[i]);\
986       tmp += insizes[i];\
987     }\
988   } else {\
989     memcpy(tmp, indatas[0], insizes[0]);\
990     tmp += ALIGN8(insizes[0]);\
991     for (i=0; i<-inndata; ++i) {\
992       memcpy(tmp, indatas[i]-chunkHeaderSize, insizes[i]+chunkHeaderSize);\
993       tmp += ALIGN8(insizes[i])+chunkHeaderSize;\
994     }\
995   }\
996 }
997
998 void CmiPushPE(int, void*);
999
1000 void          CmiSyncSendFn(int, int, char *);
1001 CmiCommHandle CmiAsyncSendFn(int, int, char *);
1002 void          CmiFreeSendFn(int, int, char *);
1003
1004 void          CmiSyncBroadcastFn(int, char *);
1005 CmiCommHandle CmiAsyncBroadcastFn(int, char *);
1006 void          CmiFreeBroadcastFn(int, char *);
1007
1008 void          CmiSyncBroadcastAllFn(int, char *);
1009 CmiCommHandle CmiAsyncBroadcastAllFn(int, char *);
1010 void          CmiFreeBroadcastAllFn(int, char *);
1011
1012 void          CmiSyncListSendFn(int, int *, int, char*);
1013 CmiCommHandle CmiAsyncListSendFn(int, int *, int, char*);
1014 void          CmiFreeListSendFn(int, int *, int, char*);
1015
1016 void          CmiSyncMulticastFn(CmiGroup, int, char*);
1017 CmiCommHandle CmiAsyncMulticastFn(CmiGroup, int, char*);
1018 void          CmiFreeMulticastFn(CmiGroup, int, char*);
1019
1020 typedef void * (*CmiReduceMergeFn)(int*,void*,void**,int);
1021 typedef void (*CmiReducePupFn)(void*,void*);
1022 typedef void (*CmiReduceDeleteFn)(void*);
1023
1024 typedef struct {
1025   void *localData;
1026   char **remoteData;
1027   int localSize;
1028   short int numRemoteReceived;
1029   short int numChildren;
1030   int parent;
1031   CmiUInt2 seqID;
1032   char localContributed;
1033   struct {
1034     CmiHandler destination;
1035     CmiReduceMergeFn mergeFn;
1036     CmiReducePupFn pupFn;
1037     CmiReduceDeleteFn deleteFn;
1038   } ops;
1039 } CmiReduction;
1040
1041 typedef CmiUInt2 CmiReductionID;
1042
1043 void * CmiReduceMergeFn_random(int*, void*, void**, int);
1044
1045 void CmiReduce(void *msg, int size, CmiReduceMergeFn mergeFn);
1046 void CmiReduceStruct(void *data, CmiReducePupFn pupFn,
1047                      CmiReduceMergeFn mergeFn, CmiHandler dest,
1048                      CmiReduceDeleteFn deleteFn);
1049 void CmiReduceID(void *msg, int size, CmiReduceMergeFn mergeFn, CmiReductionID id);
1050 void CmiReduceStructID(void *data, CmiReducePupFn pupFn,
1051                      CmiReduceMergeFn mergeFn, CmiHandler dest,
1052                      CmiReduceDeleteFn deleteFn, CmiReductionID id);
1053 void CmiListReduce(int npes, int *pes, void *msg, int size, CmiReduceMergeFn mergeFn, CmiReductionID id);
1054 void CmiListReduceStruct(int npes, int *pes,
1055                      void *data, CmiReducePupFn pupFn,
1056                      CmiReduceMergeFn mergeFn, CmiHandler dest,
1057                      CmiReduceDeleteFn deleteFn, CmiReductionID id);
1058 void CmiGroupReduce(CmiGroup grp, void *msg, int size, CmiReduceMergeFn mergeFn, CmiReductionID id);
1059 void CmiGroupReduceStruct(CmiGroup grp, void *data, CmiReducePupFn pupFn,
1060                      CmiReduceMergeFn mergeFn, CmiHandler dest,
1061                      CmiReduceDeleteFn deleteFn, CmiReductionID id);
1062 void CmiNodeReduce(void *msg, int size, CmiReduceMergeFn mergeFn, int, int, int);
1063 void CmiNodeReduceStruct(void *data, CmiReducePupFn pupFn,
1064                          CmiReduceMergeFn mergeFn, CmiHandler dest,
1065                          CmiReduceDeleteFn deleteFn);
1066 int CmiGetReductionHandler();
1067 CmiHandler CmiGetReductionDestination();
1068 CmiReductionID CmiGetGlobalReduction();
1069 CmiReductionID CmiGetDynamicReduction();
1070 void CmiGetDynamicReductionRemote(int handlerIdx, int pe, int dataSize, void *data);
1071
1072 /* If the second parameter (the number of chunks to send) is negative, then
1073  * every message will be started aligned with 8 bytes, and a message header will
1074  * be preponed to every message (message nesting), except the first one which
1075  * uses that of the entire message.
1076  */
1077 void          CmiSyncVectorSend(int, int, int *, char **);
1078 CmiCommHandle CmiAsyncVectorSend(int, int, int *, char **);
1079 void          CmiSyncVectorSendAndFree(int, int, int *, char **);
1080
1081 void          CmiMultipleSend(unsigned int, int, int *, char **);
1082 void          CmiMultipleIsend(unsigned int, int, int *, char **);
1083
1084 int           CmiAsyncMsgSent(CmiCommHandle);
1085 void          CmiReleaseCommHandle(CmiCommHandle);
1086
1087 #define CmiSyncSend(p,s,m)              (CmiSyncSendFn((p),(s),(char *)(m)))
1088 #define CmiAsyncSend(p,s,m)             (CmiAsyncSendFn((p),(s),(char *)(m)))
1089 #define CmiSyncSendAndFree(p,s,m)       (CmiFreeSendFn((p),(s),(char *)(m)))
1090
1091 #define CmiSyncBroadcast(s,m)           (CmiSyncBroadcastFn((s),(char *)(m)))
1092 #define CmiAsyncBroadcast(s,m)          (CmiAsyncBroadcastFn((s),(char *)(m)))
1093 #define CmiSyncBroadcastAndFree(s,m)    (CmiFreeBroadcastFn((s),(char *)(m)))
1094
1095 #define CmiSyncBroadcastAll(s,m)        (CmiSyncBroadcastAllFn((s),(char *)(m)))
1096 #define CmiAsyncBroadcastAll(s,m)       (CmiAsyncBroadcastAllFn((s),(char *)(m)))
1097 #define CmiSyncBroadcastAllAndFree(s,m) (CmiFreeBroadcastAllFn((s),(char *)(m)))
1098
1099 #define CmiSyncListSend(n,l,s,m)        (CmiSyncListSendFn((n),(l),(s),(char *)(m)))
1100 #define CmiAsyncListSend(n,l,s,m)       (CmiAsyncListSendFn((n),(l),(s),(char *)(m)))
1101 #define CmiSyncListSendAndFree(n,l,s,m) (CmiFreeListSendFn((n),(l),(s),(char *)(m)))
1102
1103 #define CmiSyncMulticast(g,s,m)         (CmiSyncMulticastFn((g),(s),(char*)(m)))
1104 #define CmiAsyncMulticast(g,s,m)        (CmiAsyncMulticastFn((g),(s),(char*)(m)))
1105 #define CmiSyncMulticastAndFree(g,s,m)  (CmiFreeMulticastFn((g),(s),(char*)(m)))
1106
1107 #if CMK_NODE_QUEUE_AVAILABLE
1108 void          CmiSyncNodeSendFn(int, int, char *);
1109 CmiCommHandle CmiAsyncNodeSendFn(int, int, char *);
1110 void          CmiFreeNodeSendFn(int, int, char *);
1111
1112 void          CmiSyncNodeBroadcastFn(int, char *);
1113 CmiCommHandle CmiAsyncNodeBroadcastFn(int, char *);
1114 void          CmiFreeNodeBroadcastFn(int, char *);
1115
1116 void          CmiSyncNodeBroadcastAllFn(int, char *);
1117 CmiCommHandle CmiAsyncNodeBroadcastAllFn(int, char *);
1118 void          CmiFreeNodeBroadcastAllFn(int, char *);
1119 #endif
1120
1121 #if CMK_NODE_QUEUE_AVAILABLE
1122 #define CmiSyncNodeSend(p,s,m)          (CmiSyncNodeSendFn((p),(s),(char *)(m)))
1123 #define CmiAsyncNodeSend(p,s,m)             (CmiAsyncNodeSendFn((p),(s),(char *)(m)))
1124 #define CmiSyncNodeSendAndFree(p,s,m)       (CmiFreeNodeSendFn((p),(s),(char *)(m)))
1125 #define CmiSyncNodeBroadcast(s,m)           (CmiSyncNodeBroadcastFn((s),(char *)(m)))
1126 #define CmiAsyncNodeBroadcast(s,m)          (CmiAsyncNodeBroadcastFn((s),(char *)(m)))
1127 #define CmiSyncNodeBroadcastAndFree(s,m)    (CmiFreeNodeBroadcastFn((s),(char *)(m)))
1128 #define CmiSyncNodeBroadcastAll(s,m)        (CmiSyncNodeBroadcastAllFn((s),(char *)(m)))
1129 #define CmiAsyncNodeBroadcastAll(s,m)       (CmiAsyncNodeBroadcastAllFn((s),(char *)(m)))
1130 #define CmiSyncNodeBroadcastAllAndFree(s,m) (CmiFreeNodeBroadcastAllFn((s),(char *)(m)))
1131 #else
1132
1133 #define CmiSyncNodeSend(n,s,m)        CmiSyncSend(CmiNodeFirst(n),s,m)
1134 #define CmiAsyncNodeSend(n,s,m)       CmiAsyncSend(CmiNodeFirst(n),s,m)
1135 #define CmiSyncNodeSendAndFree(n,s,m) CmiSyncSendAndFree(CmiNodeFirst(n),s,m)
1136 #if CMK_UTH_VERSION || CMK_MULTICORE
1137 #define CmiSyncNodeBroadcast(s,m)           do { \
1138           int _i; \
1139           for(_i=0; _i<CmiNumNodes(); _i++) \
1140             if(_i != CmiMyNode()) \
1141               CmiSyncSend(CmiNodeFirst(_i),s,m); \
1142         } while(0)
1143 #define CmiAsyncNodeBroadcast(s,m)          CmiSyncNodeBroadcast(s,m)
1144 #define CmiSyncNodeBroadcastAndFree(s,m)    do { \
1145           CmiSyncNodeBroadcast(s,m); \
1146           CmiFree(m); \
1147         } while(0)
1148 #define CmiSyncNodeBroadcastAll(s,m)           do { \
1149           int _i; \
1150           for(_i=0; _i<CmiNumNodes(); _i++) \
1151             CmiSyncSend(CmiNodeFirst(_i),s,m); \
1152         } while(0)
1153 #define CmiAsyncNodeBroadcastAll(s,m)       CmiSyncNodeBroadcastAll(s,m)
1154 #define CmiSyncNodeBroadcastAllAndFree(s,m) do { \
1155           CmiSyncNodeBroadcastAll(s,m); \
1156           CmiFree(m); \
1157         } while(0)
1158 #else
1159 #define CmiSyncNodeBroadcast(s,m)           CmiSyncBroadcast(s,m)
1160 #define CmiAsyncNodeBroadcast(s,m)          CmiAsyncBroadcast(s,m)
1161 #define CmiSyncNodeBroadcastAndFree(s,m)    CmiSyncBroadcastAndFree(s,m)
1162 #define CmiSyncNodeBroadcastAll(s,m)        CmiSyncBroadcastAll(s,m)
1163 #define CmiAsyncNodeBroadcastAll(s,m)       CmiAsyncBroadcastAll(s,m)
1164 #define CmiSyncNodeBroadcastAllAndFree(s,m) CmiSyncBroadcastAllAndFree(s,m)
1165 #endif
1166 #endif
1167
1168 /******** CMI MESSAGE RECEPTION ********/
1169
1170 void   CmiDeliversInit();
1171 int    CmiDeliverMsgs(int maxmsgs);
1172 void   CmiDeliverSpecificMsg(int handler);
1173 void   CmiHandleMessage(void *msg);
1174
1175 /******** CQS: THE QUEUEING SYSTEM ********
1176  * @addtogroup CharmScheduler
1177  * @{ 
1178  */
1179 #define CQS_QUEUEING_FIFO 2
1180 #define CQS_QUEUEING_LIFO 3
1181 #define CQS_QUEUEING_IFIFO 4
1182 #define CQS_QUEUEING_ILIFO 5
1183 #define CQS_QUEUEING_BFIFO 6
1184 #define CQS_QUEUEING_BLIFO 7
1185 #define CQS_QUEUEING_LFIFO 8
1186 #define CQS_QUEUEING_LLIFO 9
1187 /** @} */
1188
1189
1190 /****** CTH: THE LOW-LEVEL THREADS PACKAGE ******/
1191
1192 typedef struct CthThreadStruct *CthThread;
1193 typedef struct {
1194   /*Start with a message header so threads can be enqueued 
1195     as messages (e.g., by CthEnqueueNormalThread in convcore.c)
1196   */
1197   char cmicore[CmiReservedHeaderSize];
1198   CthThread thread;
1199   int serialNo;
1200 } CthThreadToken;
1201
1202 CthThreadToken *CthGetToken(CthThread);
1203
1204 typedef void        (*CthVoidFn)();
1205 typedef void        (*CthAwkFn)(CthThreadToken *,int,
1206                                 int prioBits,unsigned int *prioptr);
1207 typedef CthThread   (*CthThFn)();
1208
1209 void       CthSetSerialNo(CthThread t, int no);
1210 int        CthImplemented(void);
1211
1212 int        CthMigratable();
1213 CthThread  CthPup(pup_er, CthThread);
1214
1215 CthThread  CthSelf(void);
1216 CthThread  CthCreate(CthVoidFn, void *, int);
1217 CthThread  CthCreateMigratable(CthVoidFn, void *, int);
1218 void       CthResume(CthThread);
1219 void       CthFree(CthThread);
1220
1221 void       CthSetSuspendable(CthThread, int);
1222 int        CthIsSuspendable(CthThread);
1223
1224 /* added for bigsim out-of-core emulation */
1225 void       CthPrintThdMagic(CthThread); 
1226 void       CthPrintThdStack(CthThread);
1227
1228 void       CthSuspend(void);
1229 void       CthAwaken(CthThread);
1230 void       CthAwakenPrio(CthThread, int, int, unsigned int *);
1231 void       CthSetStrategy(CthThread, CthAwkFn, CthThFn);
1232 void       CthSetStrategyDefault(CthThread);
1233 void       CthYield(void);
1234 void       CthYieldPrio(int,int,unsigned int*);
1235
1236 void       CthSetNext(CthThread t, CthThread next);
1237 CthThread  CthGetNext(CthThread t);
1238
1239 void       CthSwitchThread(CthThread t);
1240
1241 size_t     CthStackOffset(CthThread t, char *p);
1242 char     * CthPointer(CthThread t, size_t pos);
1243
1244 /* unimplemented: preemptive threads */
1245 void       CthAutoYield(CthThread t, int flag);
1246 double     CthAutoYieldFreq(CthThread t);
1247 void       CthAutoYieldBlock(void);
1248 void       CthAutoYieldUnblock(void);
1249
1250 /* Converse Thread Global (Ctg) global variable manipulation */
1251 typedef struct CtgGlobalStruct *CtgGlobals;
1252
1253 /** Initialize the globals support (called on each processor). */
1254 void CtgInit(void);
1255 /** PIC method used: 0 = nop, 1 = elfgot, 2 = elfcopy */
1256 CpvExtern(int, CmiPICMethod);
1257
1258 /** Copy the current globals into this new set */
1259 CtgGlobals CtgCreate(CthThread tid);
1260 /** Install this set of globals. If g==NULL, returns to original globals. */
1261 void CtgInstall(CtgGlobals g);
1262 /** PUP this (not currently installed) globals set */
1263 CtgGlobals CtgPup(pup_er, CtgGlobals g);
1264 /** Delete this (not currently installed) set of globals. */
1265 void CtgFree(CtgGlobals g);
1266 /** Return the current global list */
1267 CtgGlobals CtgCurrentGlobals(void);
1268 void CtgInstall_var(CtgGlobals g, void *ptr);
1269 void CtgUninstall_var(CtgGlobals g, void *ptr);
1270
1271 /* The thread listener structure. The user must register one such listener
1272         if he wants to find out when a thread is suspended or when it starts running
1273         or gets destroyed. It can be used for tracing etc.
1274 */
1275
1276 struct CthThreadListener;
1277
1278 typedef void (*CthThreadListener_suspend)(struct CthThreadListener *l);
1279 typedef void (*CthThreadListener_resume)(struct CthThreadListener *l);
1280 typedef void (*CthThreadListener_free)(struct CthThreadListener *l);
1281
1282 struct CthThreadListener {
1283        /** This thread is about to block. */
1284        CthThreadListener_suspend suspend;
1285
1286        /** This thread is about to begin execution after blocking. */
1287        CthThreadListener_resume resume;
1288
1289        /** This thread is being destroyed.  */
1290        CthThreadListener_free free;
1291
1292        /** Pointer to listener-specific data (if needed).
1293            Set by listener.
1294        */
1295        void *data;
1296
1297        /** Pointer to the thread this listener controls.
1298            Set by CthAddListener.
1299         */
1300        CthThread thread;
1301
1302        /** The next listener, or NULL at end of chain.
1303            Set by CthAddListener, and used only by threads.c.
1304        */
1305        struct CthThreadListener *next;
1306 };
1307
1308 /**
1309   This listener is about to begin receiving suspend and
1310 resume events for this thread.  "suspend", "resume", "free",
1311 and "data" fields must all already be set.  When this thread
1312 exits, l->free will be called on this listener, which should
1313 deallocate the listener memory.
1314 */
1315 void CthAddListener(CthThread th,struct CthThreadListener *l);
1316
1317 /**
1318   This is function is inserted into .def.h after thread creation.
1319   It serves as an interface for the user to add the listeners 
1320   as needed. User has to implement this somewhere in the system.
1321 */
1322 void CthUserAddListeners(CthThread th);
1323
1324 /****** Isomalloc: Migratable Memory Allocation ********/
1325 /*Simple block-by-block interface:*/
1326 void *CmiIsomalloc(int sizeInBytes, CthThread tid);
1327 void *CmiIsomallocAlign(size_t align, size_t size, CthThread t);
1328 void  CmiIsomallocPup(pup_er p,void **block);
1329 void  CmiIsomallocFree(void *block);
1330 int   CmiIsomallocEnabled();
1331 void  CmiEnableIsomalloc();
1332 void  CmiDisableIsomalloc();
1333
1334 CmiInt8   CmiIsomallocLength(void *block);
1335 int   CmiIsomallocInRange(void *addr);
1336
1337 /*List-of-blocks interface:*/
1338 struct CmiIsomallocBlockList {/*Circular doubly-linked list of blocks:*/
1339         struct CmiIsomallocBlockList *prev,*next;
1340         /*actual data of block follows here...*/
1341 };
1342 typedef struct CmiIsomallocBlockList CmiIsomallocBlockList;
1343
1344 /*Build/pup/destroy an entire blockList.*/
1345 CmiIsomallocBlockList *CmiIsomallocBlockListNew(CthThread t);
1346 void CmiIsomallocBlockListPup(pup_er p,CmiIsomallocBlockList **l, CthThread tid);
1347 void CmiIsomallocBlockListDelete(CmiIsomallocBlockList *l);
1348
1349 /*Allocate/free a block from this blockList*/
1350 void *CmiIsomallocBlockListMalloc(CmiIsomallocBlockList *l,size_t nBytes);
1351 void *CmiIsomallocBlockListMallocAlign(CmiIsomallocBlockList *l,size_t align,size_t nBytes);
1352 void CmiIsomallocBlockListFree(void *doomedMallocedBlock);
1353
1354
1355 /****** CTH: THREAD-PRIVATE VARIABLES ******/
1356
1357 #if CMK_THREADS_REQUIRE_NO_CPV
1358
1359 #define CthCpvDeclare(t,v)    t v
1360 #define CthCpvExtern(t,v)     extern t v
1361 #define CthCpvStatic(t,v)     static t v
1362 #define CthCpvInitialize(t,v) do {} while(0)
1363 #define CthCpvAccess(x)       x
1364
1365 #else
1366
1367 #define CthCpvDeclare(t,v)    CpvDeclare(t,v)
1368 #define CthCpvExtern(t,v)     CpvExtern(t,v)
1369 #define CthCpvStatic(t,v)     CpvStaticDeclare(t,v)
1370 #define CthCpvInitialize(t,v) CpvInitialize(t,v)
1371 #define CthCpvAccess(x)       CpvAccess(x)
1372
1373 #endif
1374
1375 CthCpvExtern(char *,CthData);
1376 extern int CthRegister(int dataSize);
1377 extern void CthRegistered(int dataOffMax);
1378 extern char *CthGetData(CthThread t);
1379
1380 #define CtvDeclare(t,v)         typedef t CtvType##v; CsvDeclare(int,CtvOffs##v)=(-1)
1381 #define CtvStaticDeclare(t,v)   typedef t CtvType##v; CsvStaticDeclare(int,CtvOffs##v)=(-1)
1382 #define CtvExtern(t,v)          typedef t CtvType##v; CsvExtern(int,CtvOffs##v)
1383 #define CtvAccess(v)            (*((CtvType##v *)(CthCpvAccess(CthData)+CsvAccess(CtvOffs##v))))
1384 #define CtvAccessOther(t,v)            (*((CtvType##v *)(CthGetData(t)+CsvAccess(CtvOffs##v))))
1385 #define CtvInitialize(t,v)      do { \
1386         if(CsvAccess(CtvOffs##v)==(-1)) \
1387                 CsvAccess(CtvOffs##v)=CthRegister(sizeof(CtvType##v));\
1388         else CthRegistered(CsvAccess(CtvOffs##v)+sizeof(CtvType##v));\
1389 } while(0)
1390
1391 /****** CFUTURE: CONVERSE FUTURES ******/
1392
1393 typedef struct Cfuture_s
1394 {
1395   int pe;
1396   struct Cfuture_data_s *data;
1397 }
1398 Cfuture;
1399
1400 #define CfutureValueData(v) ((void*)((v)->rest))
1401
1402 Cfuture       CfutureCreate(void);
1403 void          CfutureSet(Cfuture f, void *val, int len);
1404 void         *CfutureWait(Cfuture f);
1405 void          CfutureDestroy(Cfuture f);
1406
1407 void         *CfutureCreateBuffer(int bytes);
1408 void          CfutureDestroyBuffer(void *val);
1409 void          CfutureStoreBuffer(Cfuture f, void *value);
1410
1411 #define       CfuturePE(f) ((f).pe)
1412
1413 void CfutureInit();
1414
1415 /****** CLD: THE LOAD BALANCER ******/
1416
1417 #define CLD_ANYWHERE (-1)
1418 #define CLD_BROADCAST (-2)
1419 #define CLD_BROADCAST_ALL (-3)
1420
1421 typedef void (*CldPackFn)(void *msg);
1422
1423 typedef void (*CldInfoFn)(void *msg, 
1424                           CldPackFn *packer,
1425                           int *len,
1426                           int *queueing,
1427                           int *priobits, 
1428                           unsigned int **prioptr);
1429
1430 typedef int (*CldEstimator)(void);
1431
1432 int CldRegisterInfoFn(CldInfoFn fn);
1433 int CldRegisterPackFn(CldPackFn fn);
1434 void CldRegisterEstimator(CldEstimator fn);
1435 int CldEstimate(void);
1436 char *CldGetStrategy(void);
1437
1438 void CldEnqueue(int pe, void *msg, int infofn);
1439 void CldEnqueueMulti(int npes, int *pes, void *msg, int infofn);
1440 void CldEnqueueGroup(CmiGroup grp, void *msg, int infofn);
1441 void CldNodeEnqueue(int node, void *msg, int infofn);
1442
1443 /****** CMM: THE MESSAGE MANAGER ******/
1444
1445 typedef struct CmmTableStruct *CmmTable;
1446
1447 #define CmmWildCard (-1)
1448
1449 typedef void (*CmmPupMessageFn)(pup_er p,void **msg);
1450 CmmTable CmmPup(pup_er p, CmmTable t, CmmPupMessageFn msgpup);
1451
1452 CmmTable   CmmNew();
1453 void       CmmFree(CmmTable t);
1454 void       CmmFreeAll(CmmTable t);
1455 void       CmmPut(CmmTable t, int ntags, int *tags, void *msg);
1456 void      *CmmFind(CmmTable t, int ntags, int *tags, int *returntags, int del);
1457 int        CmmEntries(CmmTable t);
1458 int        CmmGetLastTag(CmmTable t, int ntags, int *tags);
1459 #define    CmmGet(t,nt,tg,rt)   (CmmFind((t),(nt),(tg),(rt),1))
1460 #define    CmmProbe(t,nt,tg,rt) (CmmFind((t),(nt),(tg),(rt),0))
1461
1462 /******** ConverseInit and ConverseExit ********/
1463
1464 void ConverseInit(int, char**, CmiStartFn, int, int);
1465 void ConverseExit(void);
1466
1467 void CmiAbort(const char *);
1468 void CmiOutOfMemory(int nBytes);
1469
1470 #if CMK_MEMCHECK_OFF
1471 #define _MEMCHECK(p) do{}while(0)
1472 #else
1473 #define _MEMCHECK(p) do { \
1474                          if ((p)==0) CmiOutOfMemory(-1);\
1475                      } while(0)
1476 #endif
1477
1478 /******** CONVCONDS ********/
1479
1480 typedef void (*CcdVoidFn)(void *userParam,double curWallTime);
1481
1482 /*CPU conditions*/
1483 #define CcdPROCESSOR_BEGIN_BUSY 0
1484 #define CcdPROCESSOR_END_IDLE 0 /*Synonym*/
1485 #define CcdPROCESSOR_BEGIN_IDLE 1
1486 #define CcdPROCESSOR_END_BUSY 1 /*Synonym*/
1487 #define CcdPROCESSOR_STILL_IDLE 2
1488
1489 /*Periodic calls*/
1490 #define CcdPERIODIC       16 /*every few ms*/
1491 #define CcdPERIODIC_10ms  17 /*every 10ms (100Hz)*/
1492 #define CcdPERIODIC_100ms 18 /*every 100ms (10Hz)*/
1493 #define CcdPERIODIC_1second  19 /*every second*/
1494 #define CcdPERIODIC_1s       19 /*every second*/
1495 #define CcdPERIODIC_5s       20 /*every second*/
1496 #define CcdPERIODIC_5seconds 20 /*every second*/
1497 #define CcdPERIODIC_10second 21 /*every 10 seconds*/
1498 #define CcdPERIODIC_10seconds 21 /*every 10 seconds*/
1499 #define CcdPERIODIC_10s      21 /*every 10 seconds*/
1500 #define CcdPERIODIC_1minute  22 /*every minute*/
1501 #define CcdPERIODIC_2minute  23 /*every 2 minute*/
1502 #define CcdPERIODIC_5minute  24 /*every 5 minute*/
1503 #define CcdPERIODIC_10minute 25 /*every 10 minutes*/
1504 #define CcdPERIODIC_1hour    26 /*every hour*/
1505 #define CcdPERIODIC_12hour   27 /*every 12 hours*/
1506 #define CcdPERIODIC_1day     28 /*every day*/
1507
1508 /*Other conditions*/
1509 #define CcdQUIESCENCE 30
1510 #define CcdTOPOLOGY_AVAIL  31
1511 #define CcdSIGUSR1 32+1
1512 #define CcdSIGUSR2 32+2
1513
1514 /*User-defined conditions start here*/
1515 #define CcdUSER    48
1516
1517 #define CcdIGNOREPE   -2
1518 #if CMK_CONDS_USE_SPECIAL_CODE
1519 typedef int (*CmiSwitchToPEFnPtr)(int pe);
1520 extern CmiSwitchToPEFnPtr CmiSwitchToPE;
1521 #else
1522 #define CmiSwitchToPE(pe)  pe
1523 #endif
1524 void CcdCallFnAfter(CcdVoidFn fnp, void *arg, double msecs);
1525 int CcdCallOnCondition(int condnum, CcdVoidFn fnp, void *arg);
1526 int CcdCallOnConditionKeep(int condnum, CcdVoidFn fnp, void *arg);
1527 void CcdCallFnAfterOnPE(CcdVoidFn fnp, void *arg, double msecs, int pe);
1528 int CcdCallOnConditionOnPE(int condnum, CcdVoidFn fnp, void *arg, int pe);
1529 int CcdCallOnConditionKeepOnPE(int condnum, CcdVoidFn fnp, void *arg, int pe);
1530 void CcdCancelCallOnCondition(int condnum, int idx);
1531 void CcdCancelCallOnConditionKeep(int condnum, int idx);
1532 void CcdRaiseCondition(int condnum);
1533
1534 /* Command-Line-Argument handling */
1535 void CmiArgGroup(const char *parentName,const char *groupName);
1536 int CmiGetArgInt(char **argv,const char *arg,int *optDest);
1537 int CmiGetArgIntDesc(char **argv,const char *arg,int *optDest,const char *desc);
1538 int CmiGetArgLong(char **argv,const char *arg,CmiInt8 *optDest);
1539 int CmiGetArgLongDesc(char **argv,const char *arg,CmiInt8 *optDest,const char *desc);
1540 int CmiGetArgDouble(char **argv,const char *arg,double *optDest);
1541 int CmiGetArgDoubleDesc(char **argv,const char *arg,double *optDest,const char *desc);
1542 int CmiGetArgString(char **argv,const char *arg,char **optDest);
1543 int CmiGetArgStringDesc(char **argv,const char *arg,char **optDest,const char *desc);
1544 int CmiGetArgFlag(char **argv,const char *arg);
1545 int CmiGetArgFlagDesc(char **argv,const char *arg,const char *desc);
1546 void CmiDeleteArgs(char **argv,int k);
1547 int CmiGetArgc(char **argv);
1548 char **CmiCopyArgs(char **argv);
1549 int CmiArgGivingUsage(void);
1550
1551 /** 
1552    Extract the function-return pointers listed in the stack
1553    up to this depth.  nSkip is the number of enclosing functions
1554    to skip-- for example, nSkip==0 means the retPtrs[0]
1555    will be the caller of CmiBacktraceRecord.  
1556    Returns retPtrs[0..*nLevels-1] stack pointers.
1557    *nLevels may be decreased if not enough levels are available.
1558  */
1559 void CmiBacktraceRecord(void **retPtrs,int nSkip,int *nLevels);
1560
1561 /** Look up the names of these function pointers.
1562 Caller must free() the returned array, but not the individual
1563 strings.
1564 */
1565 char **CmiBacktraceLookup(void **srcPtrs,int nLevels);
1566
1567 /** Print out the names of these function pointers. */
1568 void CmiBacktracePrint(void **retPtrs,int nLevels);
1569
1570 /* Print (to stdout) the names of the functions that have been 
1571    called up to this point. nSkip is the number of routines on the
1572    top of the stack to *not* print out. */
1573 void CmiPrintStackTrace(int nSkip);
1574 int CmiIsFortranLibraryCall();
1575
1576 #if CMK_CMIDELIVERS_USE_COMMON_CODE
1577 CpvExtern(void*, CmiLocalQueue);
1578 #endif
1579
1580 char *CmiCopyMsg(char *msg, int len);
1581
1582 /******** Hypercube broadcast propagation (Binomial tree) ********/
1583
1584 /*
1585   This routing will receive a number k containing the dimension in the hypercube
1586   to be used for the broadcast, i.e. k=0 means sending only to MyPe^1, k=1 means
1587   sending to MyPe^2 and MyPe^1, etc.
1588   The array dest_pes will be filled with the id of the processors to which send,
1589   it has to be already allocated, the size should be at least k+1 to allow
1590   enough space.
1591   It return the number of processors to which send, i.e. the size of dest_pes.
1592   This may be less than k+1 due to not complete hypercubes.
1593   For example with pow(2,n)+2 procs and 0 broadcasting, proc pow(2,n) will
1594   receive from 0 in the first step but then it has only proc pow(2,n)+1 as
1595   destination, so most of the other dimentions will be skipped.
1596 */
1597 int HypercubeGetBcastDestinations(int mype, int total_pes, int k, int *dest_pes);
1598
1599 /******** Immediate Messages ********/
1600
1601 CpvExtern(int, CmiImmediateMsgHandlerIdx);
1602
1603
1604 CpvExtern(unsigned, networkProgressCount);
1605 extern int networkProgressPeriod;
1606
1607 #if !CMK_MACHINE_PROGRESS_DEFINED
1608
1609 #define CmiNetworkProgress() 
1610 #define CmiNetworkProgressAfter(p) 
1611 #define CmiMachineProgressImpl()
1612
1613 #else
1614
1615 /*#ifdef __cplusplus
1616 extern "C" 
1617 #endif*/
1618 void CmiMachineProgressImpl();
1619
1620 #define CmiNetworkProgress() {CpvAccess(networkProgressCount) ++; \
1621       if(CpvAccess(networkProgressCount) >=  networkProgressPeriod) { \
1622           CmiMachineProgressImpl(); \
1623           CpvAccess(networkProgressCount) = 0; \
1624       } \
1625 } \
1626
1627 #define CmiNetworkProgressAfter(p) {CpvAccess(networkProgressCount) ++; \
1628       if(CpvAccess(networkProgressCount) >=  p) { \
1629           CmiMachineProgressImpl(); \
1630           CpvAccess(networkProgressCount) = 0; \
1631       } \
1632 } \
1633
1634 #endif
1635
1636 #define CmiProbeImmediateMsg CmiMachineProgressImpl
1637
1638 /*
1639    to immediate-fy a Converse message, set the most significant bit to 1
1640    in the Converse handler (x|0x8000). 
1641 */
1642 #if CMK_IMMEDIATE_MSG
1643 void CmiDelayImmediate();
1644 #  define CmiBecomeImmediate(msg) do { \
1645         CmiSetHandler(msg, (CmiGetHandler(msg))|0x8000); \
1646      } while (0)
1647 #  define CmiIsImmediate(msg)      ((CmiGetHandler(msg)) & 0x8000) 
1648 #  define CmiImmediateHandler(msg) ((CmiGetHandler(msg)) ^ 0x8000)
1649 /*
1650 #  define CmiIsImmediate(msg)   ((CmiGetHandler(msg) == CpvAccessOther(CmiImmediateMsgHandlerIdx,0)))
1651 #  define CmiBecomeImmediate(msg) do {\
1652         CmiSetXHandler(msg,CmiGetHandler(msg)); \
1653         CmiSetHandler(msg,CpvAccessOther(CmiImmediateMsgHandlerIdx,0)); \
1654      } while (0)
1655 #  define CmiImemdiateHandler(msg) (CmiGetXHandler(msg))
1656 */
1657 /* 
1658   for non smp and non intr based version, it returns _immRunning
1659   for smp, this doesnot matter - CkMyPe() comparasion normaly fails and
1660            non threadsafe CqsEnqueueGeneral is avoided.
1661 */
1662 #if CMK_NET_VERSION && ! CMK_SMP && ! defined(CMK_CPV_IS_SMP)
1663 extern int _immRunning;
1664 #  define CmiImmIsRunning()        (_immRunning)
1665 #else
1666 #  define CmiImmIsRunning()        (0)
1667 #endif
1668
1669 #else
1670 #  define CmiBecomeImmediate(msg) /* empty */
1671 #  define CmiIsImmediate(msg)   (0)
1672 #  define CmiImmIsRunning()       (0)
1673 #endif
1674
1675 /******** Memory Fence ********/
1676
1677 #if  CMK_SMP
1678 #if CMK_GCC_X86_ASM
1679 #define CmiMemoryReadFence()               __asm__ __volatile__("lfence" ::: "memory")
1680 #define CmiMemoryWriteFence()              __asm__ __volatile__("sfence" ::: "memory")
1681 #if 1
1682 #define CmiMemoryAtomicIncrement(someInt)  __asm__ __volatile__("lock incl (%0)" :: "r" (&(someInt)))
1683 #define CmiMemoryAtomicDecrement(someInt)  __asm__ __volatile__("lock decl (%0)" :: "r" (&(someInt)))
1684 #else
1685 /* this might be slightly faster, but does not compile with -O3 on net-darwin-x86_64 */
1686 #define CmiMemoryAtomicIncrement(someInt)  __asm__ __volatile__("lock incl %0" :: "m" (someInt))
1687 #define CmiMemoryAtomicDecrement(someInt)  __asm__ __volatile__("lock decl %0" :: "m" (someInt))
1688 #endif
1689 #define CmiMemoryAtomicFetchAndInc(input,output) __asm__ __volatile__( \
1690         "movl $1, %1\n\t" \
1691         "lock xaddl %1, %0" \
1692         : "=m"(input), "=r"(output) : "m"(input) : "memory")
1693 #elif CMK_GCC_IA64_ASM
1694 #define CmiMemoryReadFence()               __asm__ __volatile__("mf" ::: "memory")
1695 #define CmiMemoryWriteFence()              __asm__ __volatile__("mf" ::: "memory")
1696 #define CmiMemoryAtomicIncrement(someInt)  { int someInt_private; \
1697   __asm__ __volatile__("fetchadd4.rel %0=[%1],1": "=r" (someInt_private): "r"(&someInt) :"memory"); }
1698 #define CmiMemoryAtomicDecrement(someInt)  { uint64_t someInt_private; \
1699   __asm__ __volatile__("fetchadd4.rel %0=[%1],-1": "=r" (someInt_private): "r"(&someInt) :"memory"); }
1700 #define CmiMemoryAtomicFetchAndInc(input,output) __asm__ __volatile__("fetchadd4.rel %0=[%1],1": "=r" (output): "r"(&input) :"memory")
1701 #elif CMK_PPC_ASM
1702 #define CmiMemoryReadFence()               __asm__ __volatile__("sync":::"memory")
1703 #define CmiMemoryWriteFence()              __asm__ __volatile__("sync":::"memory")
1704 #define CmiMemoryAtomicIncrement(someInt)   { int someInt_private; \
1705      __asm__ __volatile__ (      \
1706         "loop%=:\n\t"       /* repeat until this succeeds */    \
1707         "lwarx  %1,0,%2\n\t" /* reserve the operand */   \
1708         "addi   %1,%1,1\n\t" /* add incr to it */        \
1709         "stwcx. %1,0,%2\n\t" /* put the sum back, and release it */      \
1710         "bne- loop%="       /* start-over on failure */ \
1711         : "=m"(someInt), "=&r"(someInt_private)      \
1712         : "r" (&someInt), "m"(someInt)       \
1713         : "memory"  \
1714      ); }
1715 #define CmiMemoryAtomicDecrement(someInt)   { int someInt_private; \
1716      __asm__ __volatile__ (      \
1717         "loop%=:\n\t"       /* repeat until this succeeds */    \
1718         "lwarx  %1,0,%2\n\t" /* reserve the operand */   \
1719         "subi   %1,%1,1\n\t" /* add incr to it */        \
1720         "stwcx. %1,0,%2\n\t" /* put the sum back, and release it */      \
1721         "bne- loop%="       /* start-over on failure */ \
1722         : "=m"(someInt), "=&r"(someInt_private)      \
1723         : "r" (&someInt), "m"(someInt)       \
1724         : "memory"  \
1725      ); }
1726 #define CmiMemoryAtomicFetchAndInc(input,output) __asm__ __volatile__ ( \
1727         "loop%=:  lwarx %1, 0, %2\n\t" \
1728         "addi %1, %1, 1\n\t" \
1729         "stwcx. %1, 0, %2\n\t" \
1730         "bne- loop%=" \
1731         : "=m"(input), "=&r"(output) : "r"(&input), "m"(input) : "memory")
1732 #else
1733 #define CMK_NO_ASM_AVAILABLE    1
1734 extern CmiNodeLock cmiMemoryLock;
1735 #define CmiMemoryReadFence()               { CmiLock(cmiMemoryLock); CmiUnlock(cmiMemoryLock); }
1736 #define CmiMemoryWriteFence()              { CmiLock(cmiMemoryLock); CmiUnlock(cmiMemoryLock); }
1737 #define CmiMemoryAtomicIncrement(someInt)  { CmiLock(cmiMemoryLock); someInt=someInt+1; CmiUnlock(cmiMemoryLock); }
1738 #define CmiMemoryAtomicDecrement(someInt)  { CmiLock(cmiMemoryLock); someInt=someInt-1; CmiUnlock(cmiMemoryLock); }
1739 #define CmiMemoryAtomicFetchAndInc(input,output) { CmiLock(cmiMemoryLock); output=input; input=output+1; CmiUnlock(cmiMemoryLock); }
1740 #endif
1741 #else
1742 #define CmiMemoryReadFence()
1743 #define CmiMemoryWriteFence()
1744 #define CmiMemoryAtomicIncrement(someInt)  someInt=someInt+1
1745 #define CmiMemoryAtomicDecrement(someInt)  someInt=someInt-1
1746 #define CmiMemoryAtomicFetchAndInc(input,output) output=input; input=output+1;
1747 #endif
1748
1749 /******** Performance Counters ********/
1750 void CmiInitCounters();
1751 void CmiStartCounters(int events[], int numEvents);
1752 void CmiStopCounters(int events[], CMK_TYPEDEF_INT8 values[], int numEvents);
1753
1754 /******** Trace ********/
1755
1756 /* this is the type for thread ID, mainly used for projection. */
1757 #define OBJ_ID_SZ 4
1758 typedef struct _CmiObjId {
1759 int id[OBJ_ID_SZ];
1760   /* 
1761    * **CWL** Note: setting initial values to -1 does not seem to be done for 
1762    *               LDObjid. Potential consistency problems could arise. This
1763    *               will probably have to be dealt with later.
1764    */
1765 #ifdef __cplusplus
1766   _CmiObjId() { 
1767     for (int i=0; i<OBJ_ID_SZ; i++) {
1768       id[i] = -1;
1769     }
1770   }
1771   int isNull() {
1772     for (int i=0; i<OBJ_ID_SZ; i++) {
1773       if (id[i] != -1) return CmiFalse;
1774     }
1775     return CmiTrue;
1776   }
1777   CmiBool operator==(const struct _CmiObjId& objid) const {
1778     for (int i=0; i<OBJ_ID_SZ; i++) if (id[i] != objid.id[i]) return CmiFalse;
1779     return CmiTrue;
1780   }
1781 #endif
1782 } CmiObjId;
1783
1784 /* public interface for thread id acquisition */
1785 CmiObjId *CthGetThreadID(CthThread th);
1786 void CthSetThreadID(CthThread th, int a, int b, int c);
1787
1788 void CthTraceResume(CthThread t);
1789
1790 /*FAULT_EVAC */
1791 #if CMK_BIGSIM_CHARM
1792 #define CmiNodeAlive(x) (1)
1793 #else
1794 CpvExtern(char *,_validProcessors);
1795 #define CmiNodeAlive(x)  (CpvAccess(_validProcessors)[x])
1796 #endif
1797
1798 int CmiEndianness();
1799
1800 #if CMK_CHARMDEBUG
1801 extern void setMemoryTypeChare(void*); /* for memory debugging */
1802 extern void setMemoryTypeMessage(void*); /* for memory debugging */
1803 #else
1804 #define setMemoryTypeChare(p) /* empty memory debugging method */
1805 #define setMemoryTypeMessage(p) /* empty memory debugging method */
1806 #endif
1807
1808 #include "conv-cpm.h"
1809 #include "conv-cpath.h"
1810 #include "conv-qd.h"
1811 #include "conv-random.h"
1812 #include "conv-lists.h"
1813 #include "conv-trace.h"
1814 #include "persistent.h"
1815 #if CMK_CELL
1816 #include "cell-api.h"
1817 #endif
1818 #ifdef __ONESIDED_IMPL
1819 #include "conv-onesided.h"
1820 #endif
1821
1822 /* The flag tells whether we are in the process of doing out-of-core emulation in BigSim */
1823 extern int _BgOutOfCoreFlag;
1824 extern int _BgInOutOfCoreMode;
1825
1826 #ifdef ADAPT_SCHED_MEM
1827 extern int numMemCriticalEntries;
1828 extern int *memCriticalEntries;
1829 #endif
1830
1831 double CmiReadSize(const char *str);
1832
1833 #if  CMK_CONVERSE_GEMINI_UGNI
1834 void CmiTurnOnStats();
1835 void CmiTurnOffStats();
1836 #else
1837 #define CmiTurnOnStats()
1838 #define CmiTurnOffStats()
1839 #endif
1840
1841 /* CharmLibInterOperate should be a global variable as it will be
1842  * set only once by MPI ranks respectively.
1843  */
1844 extern int CharmLibInterOperate;
1845 CpvExtern(int,charmLibExitFlag);
1846
1847 /*
1848  *         Topology C wrapper
1849  */
1850 extern int CmiGetHopsBetweenRanks(int pe1, int pe2);
1851
1852 #if defined(__cplusplus)
1853 }                                         /* end of extern "C"  */
1854 #endif
1855
1856 #if CMK_GRID_QUEUE_AVAILABLE
1857 #if defined(__cplusplus)
1858 extern "C" int CmiGetCluster (int pe);
1859 extern "C" int CmiGridQueueGetInterval ();
1860 extern "C" int CmiGridQueueGetThreshold ();
1861 extern "C" void CmiGridQueueRegister (int gid, int nInts, int index1, int index2, int index3);
1862 extern "C" void CmiGridQueueDeregister (int gid, int nInts, int index1, int index2, int index3);
1863 extern "C" void CmiGridQueueDeregisterAll ();
1864 extern "C" int CmiGridQueueLookup (int gid, int nInts, int index1, int index2, int index3);
1865 extern "C" int CmiGridQueueLookupMsg (char *msg);
1866 #else
1867 extern int CmiGetCluster (int pe);
1868 extern int CmiGridQueueGetInterval ();
1869 extern int CmiGridQueueGetThreshold ();
1870 extern void CmiGridQueueRegister (int gid, int nInts, int index1, int index2, int index3);
1871 extern void CmiGridQueueDeregister (int gid, int nInts, int index1, int index2, int index3);
1872 extern void CmiGridQueueDeregisterAll ();
1873 extern int CmiGridQueueLookup (int gid, int nInts, int index1, int index2, int index3);
1874 extern int CmiGridQueueLookupMsg (char *msg);
1875 #endif
1876 #endif
1877
1878 /******** I/O wrappers ***********/
1879
1880 size_t CmiFwrite(const void *ptr, size_t size, size_t nmemb, FILE *f);
1881 FILE *CmiFopen(const char *path, const char *mode);
1882 int CmiFclose(FILE *fp);
1883
1884 #include "debug-conv.h"
1885
1886 typedef struct {
1887   CmiUInt4 msgSize;
1888   CmiUInt2 senderPe;
1889   CmiUInt2 destination;
1890 } CmiFragmentHeader;
1891
1892
1893 #if CMK_HAS_LOG2
1894 #define CmiLog2   log2
1895 #define CmiILog2  log2
1896 #else
1897 extern unsigned int CmiILog2(unsigned int);
1898 extern double CmiLog2(double);
1899 #endif
1900
1901 #if CMK_SMP && CMK_LEVERAGE_COMMTHREAD
1902 #if defined(__cplusplus)
1903 #define EXTERN extern "C"
1904 #else
1905 #define EXTERN extern
1906 #endif
1907 typedef void (*CmiCommThdFnPtr)(int numParams, void *params);
1908 typedef struct CmiNotifyCommThdMsg {
1909     char core[CmiMsgHeaderSizeBytes];
1910     CmiCommThdFnPtr fn;
1911     int numParams;
1912     void *params;
1913     int toKeep; /* whether to free this msg by comm thread when the msg is processed */ 
1914 }CmiNotifyCommThdMsg;
1915
1916 EXTERN CmiNotifyCommThdMsg *CmiCreateNotifyCommThdMsg(CmiCommThdFnPtr fn, int numParams, void *params, int toKeep);
1917 EXTERN void CmiFreeNotifyCommThdMsg(CmiNotifyCommThdMsg *msg);
1918 /* Initialize a notification msg */
1919 EXTERN void CmiResetNotifyCommThdMsg(CmiNotifyCommThdMsg *msg, CmiCommThdFnPtr fn, int numParams, void *params, int toKeep);
1920 /* Enqueue the msg into the local comm thread, and wait for being processed */
1921 EXTERN void CmiNotifyCommThd(CmiNotifyCommThdMsg *msg);
1922 #endif
1923
1924 CpvCExtern(int, _urgentSend);
1925 #if CMK_USE_OOB
1926 #define CmiEnableUrgentSend(yn)   CpvAccess(_urgentSend)=(yn)
1927 #else
1928 #define CmiEnableUrgentSend(yn)   
1929 #endif
1930
1931 #if defined(__cplusplus)
1932 extern "C" int CmiIsMyNodeIdle();
1933 #else
1934 extern int CmiIsMyNodeIdle();
1935 #endif
1936
1937 #endif /* CONVERSE_H */
1938
1939