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