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