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