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