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