Zcpy Bcast Send API: Guard ZC API macros for non-RDMA layers
[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   - Ctv, Converse thread-private variable.
22      one copy per Converse user-level thread.
23   - Cpv, Converse processor-private variable.  Very common;
24      one copy per processor of each node.
25   - Csv, Converse node-shared variable.  Global variables 
26      shared by all processors of a node (beware of thread safety!)
27
28   @ingroup CharmScheduler
29   @ingroup ConverseScheduler
30
31 */
32 #ifndef CONVERSE_H
33 #define CONVERSE_H
34
35 /*
36  * We cannot use thread_local here because "extern thread_local" variables
37  * have additional initialization semantics that the RTS does not consider.
38  * https://stackoverflow.com/a/13123870
39  *
40  * KEEPINSYNC: GKlib.h
41  */
42 #if defined _MSC_VER
43 # define CMK_THREADLOCAL __declspec(thread)
44 #else
45 # define CMK_THREADLOCAL __thread
46 #endif
47
48 #ifdef __cplusplus
49 # define CMI_EXTERNC extern "C"
50 #else
51 # define CMI_EXTERNC
52 #endif
53
54 #if defined __cplusplus && defined _MSC_VER
55 # define CMI_EXTERNC_VARIABLE extern "C"
56 #else
57 # define CMI_EXTERNC_VARIABLE extern
58 #endif
59
60 #if defined _MSC_VER
61 # define CMI_FORCE_INLINE __forceinline
62 #elif defined __GNUC__
63 # define CMI_FORCE_INLINE inline __attribute__((always_inline))
64 #else
65 # define CMI_FORCE_INLINE inline
66 #endif
67
68 #if defined(__GNUC__) && !defined(__clang__)
69 #define CMI_NOOPTIMIZE __attribute__((optimize(0)))
70 #else
71 #define CMI_NOOPTIMIZE
72 #endif
73
74 #include "conv-header.h"
75
76 #if CMK_ONESIDED_IMPL
77 #define CMI_ZC_MSGTYPE(msg)                  ((CmiMsgHeaderBasic *)msg)->zcMsgType
78 #define CMI_IS_ZC_BCAST(msg)                 (CMI_ZC_MSGTYPE(msg) == CMK_ZC_BCAST_SEND_MSG)
79 #endif
80
81 #define CMIALIGN(x,n)       (size_t)((~((size_t)n-1))&((x)+(n-1)))
82 /*#define ALIGN8(x)        (size_t)((~7)&((x)+7)) */
83 #define ALIGN8(x)          CMIALIGN(x,8)
84 #define ALIGN16(x)         CMIALIGN(x,16)
85
86 #if !defined(ALIGN_BYTES)
87 #if CMK_64BIT
88 #define ALIGN_BYTES           16U
89 #else
90 #define ALIGN_BYTES           8U
91 #endif
92 #endif
93
94 #define ALIGN_DEFAULT(x) CMIALIGN(x, ALIGN_BYTES)
95
96 #define CMIPADDING(x, n) (CMIALIGN((x), (n)) - (size_t)(x))
97
98 /**
99   Grab configuration files generated by build and configure scripts. 
100 */
101 #include "cmiqueue.h"
102
103 #include <stdio.h>
104 #include <stdlib.h>
105 #include <string.h>
106 #include <stdint.h>
107
108 #if defined __cplusplus
109 #include <atomic>
110 #endif
111
112 /* brittle accommodation of libc header internals */
113 #if defined __cplusplus && defined __THROW
114 # define CMK_THROW __THROW
115 #else
116 # define CMK_THROW
117 #endif
118
119 #ifndef __has_builtin
120 # define __has_builtin(x) 0  // Compatibility with non-clang compilers.
121 #endif
122 #if (defined __GNUC__ || __has_builtin(__builtin_unreachable)) && !defined _CRAYC
123 // Technically GCC 4.5 is the minimum for this feature, but we require C++11.
124 # define CMI_UNREACHABLE_SECTION(...) __builtin_unreachable()
125 #elif _MSC_VER
126 # define CMI_UNREACHABLE_SECTION(...) __assume(0)
127 #else
128 # define CMI_UNREACHABLE_SECTION(...) __VA_ARGS__
129 #endif
130
131 #define CMI_NORETURN_FUNCTION_END CMI_UNREACHABLE_SECTION(while(1));
132
133 # if defined __cplusplus
134 #  define CMK_NORETURN [[noreturn]]
135 # else
136 #  if defined _Noreturn
137 #   define CMK_NORETURN _Noreturn
138 #  elif defined _MSC_VER && 1200 <= _MSC_VER
139 #   define CMK_NORETURN __declspec (noreturn)
140 #  else
141 #   define CMK_NORETURN __attribute__ ((__noreturn__))
142 #  endif
143 # endif
144
145 /* Paste the tokens x and y together, without any space between them.
146    The ANSI C way to do this is the bizarre ## "token-pasting" 
147    preprocessor operator.
148  */
149 #define CMK_CONCAT(x,y) x##y
150 /* Tag variable y as being from unit x: */
151 #define CMK_TAG(x,y) x##y##_
152
153 #include "pup_c.h"
154
155 /* the following flags denote properties of the C compiler,  */
156 /* not the C++ compiler.  If this is C++, ignore them.       */
157 #ifdef __cplusplus
158
159 #if ! CMK_HAS_OFFSETOF
160 #undef offsetof
161 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
162 #else
163 #include <stddef.h>
164 #endif
165
166 extern "C" {
167 #endif
168
169 /* Global variables used by charmdebug to maintain information */
170 extern void CpdSetInitializeMemory(int v);
171 extern void CpdSystemEnter(void);
172 extern void CpdSystemExit(void);
173 #if CMK_CHARMDEBUG
174 extern int memory_status_info;
175 extern int memory_chare_id;
176 #define setMemoryStatus(p) { \
177   int tmp = memory_status_info; \
178   memory_status_info = p; \
179   p = tmp; \
180 }
181 int setMemoryChareIDFromPtr(void *p);
182 void setMemoryChareID(int id);
183 void setMemoryOwnedBy(void *p, int id);
184 #else
185 #define setMemoryStatus(p) /* empty */
186 #define setMemoryChareIDFromPtr(p) /* empty */
187 #define setMemoryChareID(p) /* empty */
188 #define setMemoryOwnedBy(p, id) /* empty */
189 #endif
190
191 /******************************************************************************
192  *
193  * Deal with Shared Memory
194  *
195  * Shared memory strongly affects how CPV, CSV, and CmiMyPe are defined,
196  * and how memory locking is performed. Therefore, we control all these
197  * functions with a single flag.
198  *
199  *****************************************************************************/
200
201 #ifdef __cplusplus
202 /* In C++, use new so t's constructor gets called */
203 # define CpvInit_Alloc(t,n) new t[n]()
204 # define CpvInit_Alloc_scalar(t) new t()
205 #else
206 # define CpvInit_Alloc(t,n) (t *)calloc(n,sizeof(t))
207 # define CpvInit_Alloc_scalar(t) (t *)calloc(1,sizeof(t))
208 #endif
209
210 extern int CmiMyRank_(void);
211
212 #if CMK_HAS_PARTITION
213
214 typedef enum Partition_Type {
215       PARTITION_SINGLETON,
216       PARTITION_DEFAULT,
217       PARTITION_MASTER,
218       PARTITION_PREFIX
219 } Partition_Type;
220
221 /* variables and functions for partition */
222 typedef struct {
223   Partition_Type type;
224   int isTopoaware, scheme;
225   int numPartitions;
226   int *partitionSize;
227   int *partitionPrefix;
228   int *nodeMap;
229   int myPartition;
230   char *partsizes;
231 } PartitionInfo;
232
233 void CmiCreatePartitions(char **argv);
234 #if defined(__cplusplus)
235 extern "C" {
236 #endif
237 void CmiSetNumPartitions(int nump);
238 void CmiSetMasterPartition(void);
239 void CmiSetPartitionSizes(char *size);
240 void CmiSetPartitionScheme(int scheme);
241 void CmiSetCustomPartitioning(void);
242 #if defined(__cplusplus)
243 }
244 #endif 
245
246 extern int _Cmi_mype_global;
247 extern int _Cmi_numpes_global;
248 extern int _Cmi_mynode_global;
249 extern int _Cmi_numnodes_global;
250 extern PartitionInfo _partitionInfo;
251
252 #define CmiNumPartitions()              _partitionInfo.numPartitions
253 #define CmiMyPartition()                _partitionInfo.myPartition
254 #define CmiPartitionSize(part)          _partitionInfo.partitionSize[part]
255 #define CmiMyPartitionSize()            CmiPartitionSize(CmiMyPartition())
256 #define CmiNumNodesGlobal()             _Cmi_numnodes_global
257 #define CmiMyNodeGlobal()               _Cmi_mynode_global
258 #define CmiNumPesGlobal()               _Cmi_numpes_global
259 /* we need different implementations of this based on SMP or non-smp */
260 #if !CMK_SMP
261 #define CmiMyPeGlobal()                 _Cmi_mype_global
262 extern int _Cmi_mynodesize;
263 #else
264 extern int CmiMyPeGlobal();
265 #endif
266
267 /* we need nodeSpan to find how many pes each node cover */
268 int CmiNodeSpan(void);
269
270 /* functions to translate between local and global */
271 int node_lToGTranslate(int node, int partition);
272 int node_gToLTranslate(int node);
273 int pe_lToGTranslate(int pe, int partition);
274 int pe_gToLTranslate(int pe);
275
276 #define CmiGetPeGlobal(pe,part)         pe_lToGTranslate(pe,part)
277 #define CmiGetNodeGlobal(node,part)     node_lToGTranslate(node,part)
278 #define CmiGetPeLocal(pe)               pe_gToLTranslate(pe)
279 #define CmiGetNodeLocal(node)           node_gToLTranslate(node)
280 /* end of variables and functions for partition */
281
282 #else
283
284 #define CmiMyPartition()         0
285 #define CmiPartitionSize(part)       CmiNumNodes()
286 #define CmiMyPartitionSize()         CmiNumNodes()
287 #define CmiNumPartitions()       1
288 #define CmiNumNodesGlobal()      CmiNumNodes()
289 #define CmiMyNodeGlobal()        CmiMyNode()
290 #define CmiNumPesGlobal()        CmiNumPes()
291 #define CmiMyPeGlobal()          CmiMyPe()
292 #if !CMK_SMP
293 extern int _Cmi_mynodesize;
294 #endif
295 #define CmiGetPeGlobal(pe,part)         (pe)
296 #define CmiGetNodeGlobal(node,part)     (node)
297 #define CmiGetPeLocal(pe)               (pe)
298 #define CmiGetNodeLocal(node)           (node)
299 #endif
300
301 typedef struct {
302   int parent;
303   int child_count;
304   int *children;
305 } CmiSpanningTreeInfo;
306
307 extern CmiSpanningTreeInfo* _topoTree; // this node's parent and children in topo-tree rooted at 0
308
309 #if CMK_SHARED_VARS_UNAVAILABLE /* Non-SMP version of shared vars. */
310 extern int _Cmi_mype;
311 extern int _Cmi_numpes;
312 extern int _Cmi_myrank; /* Normally zero; only 1 during SIGIO handling */
313 extern int _Cmi_mynode;
314 extern int _Cmi_numnodes;
315
316 #define CmiMyPe()           _Cmi_mype
317 #define CmiMyRank()         0
318 #define CmiNumPes()         _Cmi_numpes
319 #define CmiMyNodeSize()     1
320 #define CmiMyNode()         _Cmi_mype
321 #define CmiNumNodes()       _Cmi_numpes
322 #define CmiNodeFirst(node)  (node)
323 #define CmiNodeSize(node)   1
324 #define CmiNodeOf(pe)       (pe)
325 #define CmiRankOf(pe)       0
326
327 #define CpvDeclare(t,v) t CMK_TAG(Cpv_,v)[2]
328 #define CpvExtern(t,v)  extern t CMK_TAG(Cpv_,v)[2]
329 #ifdef __cplusplus
330 #define CpvCExtern(t,v)    extern "C" t CMK_TAG(Cpv_,v)[2]
331 #else
332 #define CpvCExtern(t,v)    CpvExtern(t,v)
333 #endif
334 #define CpvStaticDeclare(t,v) static t CMK_TAG(Cpv_,v)[2]
335 #define CpvInitialize(t,v) do {} while(0)
336 #define CpvInitialized(v) 1
337 #define CpvAccess(v) CMK_TAG(Cpv_,v)[_Cmi_myrank]
338 #define CpvAccessOther(v, r) CMK_TAG(Cpv_,v)[r]
339
340 extern void CmiMemLock(void);
341 extern void CmiMemUnlock(void);
342 #define CmiNodeBarrier() /*empty*/
343 #define CmiNodeAllBarrier() /*empty*/
344 #define CmiSvAlloc CmiAlloc
345
346 #if CMK_USE_LRTS /*LRTS provides locking*/
347 #include "lrtslock.h"
348 #else
349 typedef int CmiNodeLock;
350 #define CmiCreateLock() (0)
351 #define CmiLock(lock) {(lock)++;}
352 #define CmiUnlock(lock)  {(lock)--;}
353 #define CmiTryLock(lock)  ((lock)?1:((lock)=1,0))
354 #define CmiDestroyLock(lock) /*empty*/
355 #endif // CMK_USE_LRTS
356
357 #define CmiInCommThread() (0)
358
359 #endif
360
361 #if CMK_SHARED_VARS_POSIX_THREADS_SMP /*Used by the netlrts-*-smp versions*/
362
363 #include <pthread.h>
364 #include <sched.h>
365 #ifdef CMK_FAKE_SCHED_YIELD
366 #include <unistd.h>
367 #define sched_yield() sleep(0)
368 #endif
369
370 extern int _Cmi_numpes;
371 extern int _Cmi_mynodesize;
372 extern int _Cmi_mynode;
373 extern int _Cmi_numnodes;
374 extern int _Cmi_sleepOnIdle;
375 extern int _Cmi_forceSpinOnIdle;
376
377 CMI_EXTERNC
378 int CmiMyPe(void);
379 CMI_EXTERNC
380 int CmiMyRank(void);
381 #define CmiNumPes()         _Cmi_numpes
382 #define CmiMyNodeSize()     _Cmi_mynodesize
383 CMI_EXTERNC
384 int CmiNodeSize(int node);
385 #if CMK_MULTICORE
386 #define CmiMyNode()         0
387 #define CmiNumNodes()       1
388 #define CmiNodeFirst(node)  0
389 #define CmiNodeOf(pe)       0
390 #define CmiRankOf(pe)       pe
391 #else
392 #define CmiMyNode()         _Cmi_mynode
393 #define CmiNumNodes()       _Cmi_numnodes
394 CMI_EXTERNC
395 int CmiNodeFirst(int node);
396 CMI_EXTERNC
397 int CmiNodeOf(int pe);
398 CMI_EXTERNC
399 int CmiRankOf(int pe);
400 #endif
401
402 #define CMK_CPV_IS_SMP sched_yield();
403
404 extern void CmiNodeBarrier(void);
405 extern void CmiNodeAllBarrier(void);
406 #define CmiSvAlloc CmiAlloc
407
408 #if CMK_USE_LRTS
409 #include "lrtslock.h"
410 #else
411 #if CMK_HAS_SPINLOCK && CMK_USE_SPINLOCK
412 typedef pthread_spinlock_t *CmiNodeLock;
413 #define CmiLock(lock) (pthread_spin_lock(lock))
414 #define CmiUnlock(lock) (pthread_spin_unlock(lock))
415 #define CmiTryLock(lock) (pthread_spin_trylock(lock))
416 #else
417 typedef pthread_mutex_t *CmiNodeLock;
418 #define CmiLock(lock) (pthread_mutex_lock(lock))
419 #define CmiUnlock(lock) (pthread_mutex_unlock(lock))
420 #define CmiTryLock(lock) (pthread_mutex_trylock(lock))
421 #endif
422 extern CmiNodeLock CmiCreateLock(void);
423 extern void CmiDestroyLock(CmiNodeLock lock);
424 #endif // CMK_USE_LRTS
425
426 extern CmiNodeLock CmiMemLock_lock;
427 #define CmiMemLock() do{if (CmiMemLock_lock) CmiLock(CmiMemLock_lock);} while (0)
428
429 #define CmiMemUnlock() do{if (CmiMemLock_lock) CmiUnlock(CmiMemLock_lock);} while (0)
430
431
432 #if (CMK_BLUEGENEQ || CMK_PAMI_LINUX_PPC8) && CMK_ENABLE_ASYNC_PROGRESS
433 extern CMK_THREADLOCAL int32_t _cmi_bgq_incommthread;
434 #define CmiInCommThread()  (_cmi_bgq_incommthread)
435 #else
436 #define CmiInCommThread()  (CmiMyRank() == CmiMyNodeSize())
437 #endif
438
439 #endif /* POSIX_THREADS_SMP */
440
441 #include "string.h"
442
443 #if CMK_BLUEGENEQ && CMK_BLUEGENEQ_OPTCOPY
444 void CmiMemcpy_qpx (void *dst, const void *src, size_t n);
445 #define CmiMemcpy(_dst, _src, _n)                                        \
446   do {                                                                   \
447     const void *_cmimemcpy_src = (_src);                                 \
448     void *_cmimemcpy_dst = (_dst);                                       \
449     size_t _cmimemcpy_n = (_n);                                          \
450     if ( (_cmimemcpy_n > 512+32) &&                                      \
451          ((((size_t)_cmimemcpy_dst|(size_t)_cmimemcpy_src) & 0x1F)==0) ) \
452       CmiMemcpy_qpx(_cmimemcpy_dst, _cmimemcpy_src, _cmimemcpy_n);       \
453     else                                                                 \
454       memcpy(_cmimemcpy_dst, _cmimemcpy_src, _cmimemcpy_n);              \
455   } while(0)
456 #else
457 #define CmiMemcpy(dest, src, size) memcpy((dest), (src), (size))
458 #endif
459
460 #if CMK_SHARED_VARS_UNIPROCESSOR /*Used only by uth- and sim- versions*/
461
462 extern int _Cmi_mype;
463 extern int _Cmi_numpes;
464
465 #define CmiMyPe()              _Cmi_mype
466 #define CmiMyRank()            _Cmi_mype
467 #define CmiNumPes()            _Cmi_numpes
468 #define CmiMyNodeSize()        _Cmi_numpes
469 #define CmiMyNode()            0
470 #define CmiNumNodes()          1
471 #define CmiNodeFirst(node)     0
472 #define CmiNodeSize(node)      _Cmi_numpes
473 #define CmiNodeOf(pe)          0
474 #define CmiRankOf(pe)          (pe)
475
476 #define CpvDeclare(t,v) t* CMK_TAG(Cpv_,v)
477 #define CpvExtern(t,v)  extern t* CMK_TAG(Cpv_,v)
478 #ifdef __cplusplus
479 #define CpvCExtern(t,v)  extern "C" t* CMK_TAG(Cpv_,v)
480 #else
481 #define CpvCExtern(t,v)    CpvExtern(t,v)
482 #endif
483 #define CpvStaticDeclare(t,v) static t* CMK_TAG(Cpv_,v)
484 #define CpvInitialize(t,v)\
485   do  { if (CMK_TAG(Cpv_,v)==0)\
486         { CMK_TAG(Cpv_,v) = CpvInit_Alloc(t,CmiNumPes()); }}\
487   while(0)
488 #define CpvInitialized(v) (0!=CMK_TAG(Cpv_,v))
489 #define CpvAccess(v) CMK_TAG(Cpv_,v)[CmiMyPe()]
490 #define CpvAccessOther(v, r) CMK_TAG(Cpv_,v)[r]
491
492 #define CmiMemLock() 0
493 #define CmiMemUnlock() 0
494 extern void CmiNodeBarrier(void);
495 extern void CmiNodeAllBarrier(void);
496 #define CmiSvAlloc CmiAlloc
497
498 typedef int *CmiNodeLock;
499 extern CmiNodeLock  CmiCreateLock(void);
500 extern void         CmiLock(CmiNodeLock lock);
501 extern void         CmiUnlock(CmiNodeLock lock);
502 extern int          CmiTryLock(CmiNodeLock lock);
503 extern void         CmiDestroyLock(CmiNodeLock lock);
504
505 #endif
506
507 #if CMK_SHARED_VARS_NT_THREADS /*Used only by win versions*/
508
509 #ifndef WIN32_LEAN_AND_MEAN
510 #define WIN32_LEAN_AND_MEAN
511 #endif
512 #include <windows.h>
513 #include "lrtslock.h"
514
515 extern int _Cmi_numpes;
516 extern int _Cmi_mynodesize;
517 extern int _Cmi_mynode;
518 extern int _Cmi_numnodes;
519 extern int _Cmi_sleepOnIdle;
520 extern int _Cmi_forceSpinOnIdle;
521
522 CMI_EXTERNC
523 int CmiMyPe(void);
524 CMI_EXTERNC
525 int CmiMyRank(void);
526 #define CmiNumPes()         _Cmi_numpes
527 #define CmiMyNodeSize()     _Cmi_mynodesize
528 CMI_EXTERNC
529 int CmiNodeSize(int node);
530 #if CMK_MULTICORE
531 #define CmiMyNode()         0
532 #define CmiNumNodes()       1
533 #define CmiNodeFirst(node)  0
534 #define CmiNodeOf(pe)       0
535 #define CmiRankOf(pe)       pe
536 #else
537 #define CmiMyNode()         _Cmi_mynode
538 #define CmiNumNodes()       _Cmi_numnodes
539 CMI_EXTERNC
540 int CmiNodeFirst(int node);
541 CMI_EXTERNC
542 int CmiNodeOf(int pe);
543 CMI_EXTERNC
544 int CmiRankOf(int pe);
545 #endif
546
547 #define CMK_CPV_IS_SMP Sleep(0);
548
549 extern void CmiNodeBarrier(void);
550 extern void CmiNodeAllBarrier(void);
551 #define CmiSvAlloc CmiAlloc
552
553 extern CmiNodeLock CmiMemLock_lock;
554 #define CmiMemLock() do{if (CmiMemLock_lock) CmiLock(CmiMemLock_lock);} while (0)
555 #define CmiMemUnlock() do{if (CmiMemLock_lock) CmiUnlock(CmiMemLock_lock);} while (0)
556
557 #endif
558
559 #if CMK_SHARED_VARS_UNAVAILABLE /* non-SMP version */
560
561 typedef int CmiImmediateLockType;
562 extern int _immediateLock;
563 extern int _immediateFlag;
564 #define CmiCreateImmediateLock() (0)
565 #define CmiImmediateLock(ignored) { _immediateLock++; }
566 #if CMK_IMMEDIATE_MSG
567 #define CmiImmediateUnlock(ignored) \
568   { _immediateLock--; \
569     if(_immediateFlag) \
570       CmiProbeImmediateMsg(); } 
571 #else
572 #define CmiImmediateUnlock(ignored) { _immediateLock--; }
573 #endif
574 #define CmiCheckImmediateLock(ignored) \
575   ((_immediateLock)?((_immediateFlag=1),1):0)
576 #define CmiClearImmediateFlag() { _immediateFlag=0; }
577
578 #else /* SMP and all other weird versions */
579
580 typedef CmiNodeLock CmiImmediateLockType;
581 #define CmiCreateImmediateLock() CmiCreateLock()
582 #define CmiImmediateLock(immediateLock) CmiLock((immediateLock))
583 #define CmiImmediateUnlock(immediateLock) CmiUnlock((immediateLock)) 
584 #define CmiCheckImmediateLock(ignored)  (0)
585 #define CmiClearImmediateFlag() 
586
587 #endif
588
589 /* This is the default Cpv implmentation for SMP-style systems:
590 A Cpv variable is actually a pointer to an array of values, one
591 for each processor in the node.
592 */
593 #ifdef CMK_CPV_IS_SMP
594
595 #if CMK_HAS_TLS_VARIABLES && !CMK_NOT_USE_TLS_THREAD
596 #define CpvDeclare(t,v) CMK_THREADLOCAL t* CMK_TAG(Cpv_,v) = NULL;   \
597                         int CMK_TAG(Cpv_inited_,v) = 0;  \
598                         t ** CMK_TAG(Cpv_addr_,v)
599 #define CpvExtern(t,v)  extern CMK_THREADLOCAL t* CMK_TAG(Cpv_,v);  \
600                         extern int CMK_TAG(Cpv_inited_,v);  \
601                         extern t ** CMK_TAG(Cpv_addr_,v)
602 #ifdef __cplusplus
603 #define CpvCExtern(t,v) extern "C" CMK_THREADLOCAL t* CMK_TAG(Cpv_,v);  \
604                         extern "C" int CMK_TAG(Cpv_inited_,v);  \
605                         extern "C" t ** CMK_TAG(Cpv_addr_,v)
606 #else
607 #define CpvCExtern(t,v)    CpvExtern(t,v)
608 #endif
609 #define CpvStaticDeclare(t,v) static CMK_THREADLOCAL t* CMK_TAG(Cpv_,v) = NULL;   \
610                         static int CMK_TAG(Cpv_inited_,v) = 0;  \
611                         static t ** CMK_TAG(Cpv_addr_,v)
612 #define CpvInitialize(t,v)\
613     do {                                                               \
614       CmiMemLock();                                                    \
615       if (!(CMK_TAG(Cpv_inited_,v))) {                                 \
616         CMK_TAG(Cpv_addr_,v) = CpvInit_Alloc(t*, 1+CmiMyNodeSize());   \
617         CMK_TAG(Cpv_inited_,v) = 1;                                    \
618       }                                                                \
619       CmiMemUnlock();                                                  \
620       CMK_TAG(Cpv_,v) = CpvInit_Alloc_scalar(t);                       \
621       CMK_TAG(Cpv_addr_,v)[CmiMyRank()] = CMK_TAG(Cpv_,v);             \
622     } while(0)
623 #define CpvInitialized(v) (0!=CMK_TAG(Cpv_,v))
624
625 #if (CMK_BLUEGENEQ || CMK_PAMI_LINUX_PPC8) && CMK_ENABLE_ASYNC_PROGRESS && CMK_IMMEDIATE_MSG
626   #define CpvAccess(v) (*(CMK_TAG(Cpv_addr_,v)[CmiMyRank()]))
627 #else
628 #define CpvAccess(v) (*CMK_TAG(Cpv_,v))
629 #endif
630
631 #define CpvAccessOther(v, r) (*(CMK_TAG(Cpv_addr_,v)[r]))
632 #else
633
634 #define CpvDeclare(t,v) t* CMK_TAG(Cpv_,v)
635 #define CpvExtern(t,v)  extern t* CMK_TAG(Cpv_,v)
636 #ifdef __cplusplus
637 #define CpvCExtern(t,v)    extern "C" t* CMK_TAG(Cpv_,v)
638 #else
639 #define CpvCExtern(t,v)    CpvExtern(t,v)
640 #endif
641 #define CpvStaticDeclare(t,v) static t* CMK_TAG(Cpv_,v)
642 #define CpvInitialize(t,v)\
643     do { \
644        if (CmiMyRank()) { \
645                CmiMemoryReadFence(); \
646                        while (!CpvInitialized(v)) { CMK_CPV_IS_SMP ; CmiMemoryReadFence(); } \
647        } else { \
648                t* tmp = CpvInit_Alloc(t,1+CmiMyNodeSize());\
649                CmiMemoryWriteFence();   \
650                CMK_TAG(Cpv_,v)=tmp;   \
651                /* CMK_TAG(Cpv_,v)=CpvInit_Alloc(t,1+CmiMyNodeSize()); */\
652        } \
653     } while(0)
654 #define CpvInitialized(v) (0!=CMK_TAG(Cpv_,v))
655 #define CpvAccess(v) CMK_TAG(Cpv_,v)[CmiMyRank()]
656 #define CpvAccessOther(v, r) CMK_TAG(Cpv_,v)[r]
657 #endif
658
659 #endif
660
661 /*Csv are the same almost everywhere:*/
662 #ifndef CsvDeclare
663 #define CsvDeclare(t,v) t CMK_TAG(Csv_,v)
664 #define CsvStaticDeclare(t,v) static t CMK_TAG(Csv_,v)
665 #define CsvExtern(t,v) extern t CMK_TAG(Csv_,v)
666 #define CsvInitialize(t,v) do{}while(0)
667 #define CsvInitialized(v) 1
668 #define CsvAccess(v) CMK_TAG(Csv_,v)
669 #endif
670
671 extern CmiNodeLock _smp_mutex;
672
673 extern int CmiBarrier(void);
674 extern int CmiBarrierZero(void);
675
676 /* cpu topology */
677 extern int CmiNumCores(void);
678 extern int CmiCpuTopologyEnabled(void);
679 extern int CmiPeOnSamePhysicalNode(int pe1, int pe2);
680 extern int CmiNumPhysicalNodes(void);
681 extern int CmiPhysicalNodeID(int pe);
682 extern int CmiNumPesOnPhysicalNode(int node);
683 extern void CmiGetPesOnPhysicalNode(int node, int **pelist, int *num);
684 extern int CmiGetFirstPeOnPhysicalNode(int node);
685 extern int CmiPhysicalRank(int pe);
686 extern void CmiInitCPUAffinity(char **argv);
687 extern int CmiPrintCPUAffinity(void);
688 extern int CmiSetCPUAffinity(int core);
689 extern void CmiInitCPUTopology(char **argv);
690 extern int CmiOnCore(void);
691
692 typedef struct
693 {
694   int num_pus;
695   int num_cores;
696   int num_sockets;
697 } CmiHwlocTopology;
698
699 extern CmiHwlocTopology CmiHwlocTopologyLocal;
700
701 extern void CmiInitHwlocTopology(void);
702
703 /** Return 1 if our outgoing message queue 
704    for this node is longer than this many bytes. */
705 int CmiLongSendQueue(int forNode,int longerThanBytes);
706
707 /******** CMI, CSD: MANY LOW-LEVEL OPERATIONS ********/
708
709 typedef struct {
710         CmiHandlerEx hdlr;
711         void *userPtr;
712 } CmiHandlerInfo;
713
714 #include "queueing.h" /* for "Queue" */
715
716 CpvExtern(CmiHandlerInfo*, CmiHandlerTable);
717 CpvExtern(int,         CmiHandlerMax);
718 CpvExtern(Queue,       CsdSchedQueue);
719 #if CMK_SMP && CMK_TASKQUEUE
720 CpvExtern(Queue,       CsdTaskQueue);
721 CpvExtern(void*,       CmiSuspendedTaskQueue);
722 #endif
723 #if CMK_GRID_QUEUE_AVAILABLE
724 CpvExtern(Queue,      CsdGridQueue);
725 #endif
726 #if CMK_OBJECT_QUEUE_AVAILABLE
727 CpvExtern(Queue,       CsdObjQueue);
728 #endif
729 #if CMK_NODE_QUEUE_AVAILABLE
730 CsvExtern(Queue,       CsdNodeQueue);
731 CsvExtern(CmiNodeLock, CsdNodeQueueLock);
732 #endif
733 CpvExtern(int,         CsdStopFlag);
734 CpvExtern(int,         CsdLocalCount);
735 #define CSD_LOCAL_MAX_DEFAULT 0
736
737 extern void CmiAssignOnce(int* variable, int value);
738
739 extern int CmiRegisterHandler(CmiHandler h);
740 extern int CmiRegisterHandlerEx(CmiHandlerEx h,void *userPtr);
741 #if CMI_LOCAL_GLOBAL_AVAILABLE
742 extern int CmiRegisterHandlerLocal(CmiHandler);
743 extern int CmiRegisterHandlerGlobal(CmiHandler);
744 #endif
745 extern void CmiNumberHandler(int n, CmiHandler h);
746 extern void CmiNumberHandlerEx(int n, CmiHandlerEx h,void *userPtr);
747
748 #define CmiGetHandler(m)  (((CmiMsgHeaderExt*)m)->hdl)
749 #define CmiGetXHandler(m) (((CmiMsgHeaderExt*)m)->xhdl)
750 #define CmiGetInfo(m)     (((CmiMsgHeaderExt*)m)->info)
751 #define CmiGetRoot(m)     (((CmiMsgHeaderExt*)m)->root)
752 #define CmiGetRedID(m)    (((CmiMsgHeaderExt*)m)->redID)
753
754 #define CmiSetHandler(m,v)  do {((((CmiMsgHeaderExt*)m)->hdl)=(v));} while(0)
755 #define CmiSetXHandler(m,v) do {((((CmiMsgHeaderExt*)m)->xhdl)=(v));} while(0)
756 #define CmiSetInfo(m,v)     do {((((CmiMsgHeaderExt*)m)->info)=(v));} while(0)
757 #define CmiSetRoot(m,v)     do {((((CmiMsgHeaderExt*)m)->root)=(v));} while(0)
758 #define CmiSetRedID(m,v)    do {((((CmiMsgHeaderExt*)m)->redID)=(v));} while(0)
759
760 #define CmiHandlerToInfo(n) (CpvAccess(CmiHandlerTable)[n])
761 #define CmiHandlerToFunction(n) (CmiHandlerToInfo(n).hdlr)
762 #define CmiGetHandlerInfo(env) (CmiHandlerToInfo(CmiGetHandler(env)))
763 #define CmiGetHandlerFunction(env) (CmiHandlerToFunction(CmiGetHandler(env)))
764
765 #if __FAULT__
766 CpvExtern(int, _curRestartPhase);      /* number of restarts */
767 #endif
768
769 #if CMK_MEM_CHECKPOINT
770 #undef CmiSetHandler
771 #define CmiSetHandler(m,v)  do {(((CmiMsgHeaderExt*)m)->hdl)=(v); (((CmiMsgHeaderExt*)m)->pn)=CpvAccess(_curRestartPhase);} while(0)
772 #define MESSAGE_PHASE_CHECK(msg)        \
773         {       \
774           int phase = CmiGetRestartPhase(msg);  \
775           if (phase != 9999 && phase < CpvAccess(_curRestartPhase)) {   \
776             /* CmiPrintf("[%d] discard message of phase %d cur_restart_phase:%d. \n", CmiMyPe(), phase, cur_restart_phase); */  \
777             CmiFree(msg);       \
778             return;     \
779           }     \
780           /* CmiAssert(phase == cur_restart_phase || phase == 9999); */ \
781           if (phase > CpvAccess(_curRestartPhase) && phase != 9999) {    \
782             /* CmiPrintf("[%d] enqueue message of phase %d cur_restart_phase:%d. \n", CmiMyPe(), phase, cur_restart_phase); */  \
783             CsdEnqueueFifo(msg);    \
784             return;     \
785           }     \
786         }
787 #else
788 #define MESSAGE_PHASE_CHECK(msg)
789 #endif
790
791 #if defined __cplusplus
792
793 /** This header goes before each chunk of memory allocated with CmiAlloc. 
794     See the comment in convcore.C for details on the fields.
795 */
796 struct CmiChunkHeader {
797   int size;
798 private:
799 #if CMK_SMP
800   std::atomic<int> ref;
801 #else
802   int ref;
803 #endif
804 #if ALIGN_BYTES > 8
805   #if defined(__GNUC__) || defined(__clang__)
806   #pragma GCC diagnostic push
807   #pragma GCC diagnostic ignored "-Wpedantic"
808   #if defined(__clang__)
809   #pragma GCC diagnostic ignored "-Wunused-private-field"
810   #endif
811   #endif
812   char align[ALIGN_BYTES
813              - sizeof(int)*2
814 #if (CMK_USE_IBVERBS || CMK_USE_IBUD)
815              - sizeof(void *)
816 #endif
817             ];
818   #if defined(__GNUC__) || defined(__clang__)
819   #pragma GCC diagnostic pop
820   #endif
821 #endif
822 public:
823   CmiChunkHeader() = default;
824   CmiChunkHeader(const CmiChunkHeader & x)
825     : size{x.size}, ref{x.getRef()} { }
826 #if CMK_SMP
827   int getRef() const
828   {
829     return ref.load(std::memory_order_acquire);
830   }
831   void setRef(int r)
832   {
833     return ref.store(r, std::memory_order_release);
834   }
835   int incRef()
836   {
837     return ref.fetch_add(1, std::memory_order_release);
838   }
839   int decRef()
840   {
841     return ref.fetch_sub(1, std::memory_order_release);
842   }
843 #else
844   int getRef() const { return ref; }
845   void setRef(int r) { ref = r; }
846   int incRef() { return ref++; }
847   int decRef() { return ref--; }
848 #endif
849 };
850
851 #if CMK_USE_IBVERBS | CMK_USE_IBUD
852 struct infiCmiChunkMetaDataStruct;
853
854 #define CMI_INFI_CHUNK_HEADER_FIELDS \
855 struct infiCmiChunkMetaDataStruct *metaData;\
856 CmiChunkHeader chunkHeader;
857
858 struct infiCmiChunkHeaderHelper{
859   CMI_INFI_CHUNK_HEADER_FIELDS
860 };
861
862 typedef struct infiCmiChunkHeaderStruct{
863   CMI_INFI_CHUNK_HEADER_FIELDS
864 } infiCmiChunkHeader;
865
866 struct infiCmiChunkMetaDataStruct *registerMultiSendMesg(char *msg,int msgSize);
867 #endif
868
869 /* Given a user chunk m, extract the enclosing chunk header fields: */
870 #define BLKSTART(m) ((CmiChunkHeader *) (((intptr_t)m) - sizeof(CmiChunkHeader)))
871 #define SIZEFIELD(m) ((BLKSTART(m))->size)
872 #define REFFIELD(m) ((BLKSTART(m))->getRef())
873 #define REFFIELDSET(m, r) ((BLKSTART(m))->setRef(r))
874 #define REFFIELDINC(m) ((BLKSTART(m))->incRef())
875 #define REFFIELDDEC(m) ((BLKSTART(m))->decRef())
876
877 #endif
878
879 CMI_EXTERNC void* malloc_nomigrate(size_t size);
880 CMI_EXTERNC void free_nomigrate(void* ptr);
881
882 /**
883    Allocate `size` bytes of memory usable as a message buffer.
884
885    Such memory may be in limited supply and expensive to obtain on
886    machine layers that use registered or pinned memory when
887    interacting with the communication hardware. Uses besides buffers
888    in which to construct messages should prefer the malloc()/free()
889    provided by libmemory-*.
890 */
891 void    *CmiAlloc(int size);
892 void     CmiReference(void *blk);
893 int      CmiGetReference(void *blk);
894 int      CmiSize(void *blk);
895 void     CmiFree(void *blk);
896 void     CmiRdmaFree(void *blk);
897
898 #ifndef CMI_TMP_SKIP
899 void *CmiTmpAlloc(int size);
900 void CmiTmpFree(void *);
901 #endif
902
903 /* Pool features */
904
905
906 /* Various special features of certain -memory modes: */
907 extern void * memory_stack_top; /* contains the top of the stack, for -memory charmdebug */
908 void CmiMemoryCheck(void); /* heap check, for -memory paranoid */
909 void CmiMemoryMark(void); /* ignore current allocations, for -memory leak */
910 void CmiMemoryMarkBlock(void *blk); /* ignore this allocation, for -memory leak */
911 void CmiMemorySweep(const char *where); /* print current allocations, for -memory leak */
912 CMK_TYPEDEF_UINT8 CmiMemoryUsage();
913 const char *CmiMemoryUsageReporter();
914 CMK_TYPEDEF_UINT8 CmiMaxMemoryUsageR(void);
915 CMK_TYPEDEF_UINT8 CmiMaxMemoryUsage();
916 void CmiResetMaxMemory();
917 CMK_TYPEDEF_UINT8 CmiMinMemoryUsage();
918 void CmiResetMinMemory();
919
920 /* General functions for malloc'ing aligned buffers */
921 #define CmiRoundUpToPow2(s, p2)  (s + ((p2 - (s & (p2 - 1))) & (p2 - 1)))
922 void* CmiMallocAligned(const size_t size, const unsigned int alignment);
923 void CmiFreeAligned(void* ptr);
924
925 #define CMI_MEMORY_IS_ISOMALLOC   (1<<1)
926 #define CMI_MEMORY_IS_PARANOID    (1<<2)
927 #define CMI_MEMORY_IS_GNU         (1<<3)
928 #define CMI_MEMORY_IS_GNUOLD      (1<<4)
929 #define CMI_MEMORY_IS_OS          (1<<5)
930 #define CMI_MEMORY_IS_CHARMDEBUG  (1<<6)
931 int CmiMemoryIs(int flag); /* return state of this flag */
932
933 #define CMI_THREAD_IS_QT         (1<<1)
934 #define CMI_THREAD_IS_CONTEXT    (1<<2)
935 #define CMI_THREAD_IS_UJCONTEXT  (1<<3)
936 #define CMI_THREAD_IS_PTHREADS   (1<<4)
937 #define CMI_THREAD_IS_FIBERS     (1<<5)
938 #define CMI_THREAD_IS_ALIAS      (1<<6)
939 #define CMI_THREAD_IS_STACKCOPY  (1<<7)
940 #define CMI_THREAD_IS_TLS        (1<<8)
941 int CmiThreadIs(int flag); /* return state of this flag */
942
943 void CmiMkdir(const char *dirName);
944 int CmiGetPageSize(void);
945
946 double   CmiCpuTimer(void);
947
948 #if CMK_TIMER_USE_RDTSC 
949 #ifndef __x86_64__
950 # if !CMK_GCC_X86_ASM
951 /* Can't use rdtsc unless we have x86 assembly: */
952 #  undef CMK_TIMER_USE_RDTSC
953 #  undef CMK_TIMER_USE_GETRUSAGE
954 #  define CMK_TIMER_USE_RDTSC 0
955 #  define CMK_TIMER_USE_GETRUSAGE 1
956 # endif
957 #endif
958 #endif
959
960 #if CMK_TIMER_USE_RDTSC 
961 extern double _cpu_speed_factor;
962
963 static __inline__ unsigned long long int rdtsc(void)
964 {
965         unsigned long long int x;
966 #ifdef __x86_64__
967         /* taken from papi code ("perfctr-p3.c") for machines like opteron */
968         do {
969           unsigned int a,d;
970           asm volatile("rdtsc" : "=a" (a), "=d" (d));
971           (x) = ((unsigned long)a) | (((unsigned long)d)<<32);
972         } while(0);
973 #elif CMK_GCC_X86_ASM
974         __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
975 #else
976 #  error "Unknown assembly format-- can't use CMK_TIMER_USE_RDTSC."
977 #endif
978         return x;
979 }
980
981 #define CmiWallTimer() ((double)rdtsc()*(_cpu_speed_factor))
982 #define CmiTimer CmiCpuTimer
983 double   CmiStartTimer(void);
984 double   CmiInitTime(void);
985 #define CmiTimerIsSynchronized()        (0)
986 #define CmiTimerAbsolute()              (0)
987
988 #else
989 void     CmiTimerInit(char **argv);
990 int      CmiTimerAbsolute(void);
991 double   CmiStartTimer(void);
992 double   CmiInitTime(void);
993 double   CmiTimer(void);
994 double   CmiWallTimer(void);
995 int      CmiTimerIsSynchronized(void);
996 #endif
997
998 char *CmiPrintDate(void);
999
1000 #if CMK_NODE_QUEUE_AVAILABLE
1001
1002 #define CsdNodeEnqueueGeneral(x,s,i,p) do { \
1003           CmiLock(CsvAccess(CsdNodeQueueLock));\
1004           CqsEnqueueGeneral((Queue)CsvAccess(CsdNodeQueue),(x),(s),(i),(p)); \
1005           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
1006         } while(0)
1007 #define CsdNodeEnqueueFifo(x)     do { \
1008           CmiLock(CsvAccess(CsdNodeQueueLock));\
1009           CqsEnqueueFifo((Queue)CsvAccess(CsdNodeQueue),(x)); \
1010           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
1011         } while(0)
1012 #define CsdNodeEnqueueLifo(x)     do { \
1013           CmiLock(CsvAccess(CsdNodeQueueLock));\
1014           CqsEnqueueLifo((Queue)CsvAccess(CsdNodeQueue),(x))); \
1015           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
1016         } while(0)
1017 #define CsdNodeEnqueue(x)     do { \
1018           CmiLock(CsvAccess(CsdNodeQueueLock));\
1019           CqsEnqueueFifo((Queue)CsvAccess(CsdNodeQueue),(x));\
1020           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
1021         } while(0)
1022
1023 #define CsdNodeEmpty()            (CqsEmpty(C(Queue)pvAccess(CsdNodeQueue)))
1024 #define CsdNodeLength()           (CqsLength((Queue)CpvAccess(CsdNodeQueue)))
1025
1026 #else
1027
1028 #define CsdNodeEnqueueGeneral(x,s,i,p) (CsdEnqueueGeneral(x,s,i,p))
1029 #define CsdNodeEnqueueFifo(x) (CqsEnqueueFifo((Queue)CpvAccess(CsdSchedQueue),(x)))
1030 #define CsdNodeEnqueueLifo(x) (CqsEnqueueLifo((Queue)CpvAccess(CsdSchedQueue),(x)))
1031 #define CsdNodeEnqueue(x)     (CsdEnqueue(x))
1032 #define CsdNodeEmpty()        (CqsEmpty((Queue)CpvAccess(CsdSchedQueue)))
1033 #define CsdNodeLength()       (CqsLength((Queue)CpvAccess(CsdSchedQueue)))
1034
1035 #endif
1036
1037 #define CsdEnqueueGeneral(x,s,i,p)\
1038     (CqsEnqueueGeneral((Queue)CpvAccess(CsdSchedQueue),(x),(s),(i),(p)))
1039 #define CsdEnqueueFifo(x)     (CqsEnqueueFifo((Queue)CpvAccess(CsdSchedQueue),(x)))
1040 #define CsdEnqueueLifo(x)     (CqsEnqueueLifo((Queue)CpvAccess(CsdSchedQueue),(x)))
1041 #define CsdEnqueue(x)         (CqsEnqueueFifo((Queue)CpvAccess(CsdSchedQueue),(x)))
1042 #define CsdEmpty()            (CqsEmpty((Queue)CpvAccess(CsdSchedQueue)))
1043 #define CsdLength()           (CqsLength((Queue)CpvAccess(CsdSchedQueue)))
1044 #if CMK_CMIPRINTF_IS_A_BUILTIN /* these are implemented in machine.C */
1045 void  CmiPrintf(const char *, ...);
1046 void  CmiError(const char *, ...);
1047 int   CmiScanf(const char *, ...);
1048 /* CmiFlush is disabled in this case */
1049 #define CmiFlush(stream) 
1050
1051 #else /* standard definitions */
1052
1053 #include <stdio.h>
1054
1055 /*
1056  * I made vprintf functions for CmiPrintf and CmiError, but on the
1057  * O2K, there is no equivalent vscanf!
1058
1059  #define CmiPrintf printf
1060  #define CmiError  printf
1061 */
1062 #include <stdarg.h>
1063
1064 void  CmiPrintf(const char *format, ...);
1065 void  CmiError(const char *format, ...);
1066 /* CmiFlush works only when CMK_CMIPRINTF_IS_A_BUILTIN is false */
1067 #define CmiFlush(stream)  fflush(stream);
1068 #define CmiScanf  scanf
1069
1070 #endif
1071
1072 #if defined(__STDC__) || defined(__cplusplus)
1073 #define __CMK_STRING(x) #x
1074 #else
1075 #define __CMK_STRING(x) "x"
1076 #endif
1077
1078 #define __CMK_XSTRING(x) __CMK_STRING(x)
1079
1080 extern void __cmi_assert(const char *);
1081 #define CmiEnforce(expr) \
1082   ((void) ((expr) ? 0 :                   \
1083      (__cmi_assert ("Assertion \"" __CMK_STRING(expr) \
1084                     "\" failed in file " __FILE__ \
1085                     " line " __CMK_XSTRING(__LINE__) "."), 0)))
1086
1087 #if ! CMK_ERROR_CHECKING
1088 #define CmiAssert(expr) ((void) 0)
1089 #else
1090 #define CmiAssert(expr) \
1091   ((void) ((expr) ? 0 :                   \
1092      (__cmi_assert ("Assertion \"" __CMK_STRING(expr) \
1093                     "\" failed in file " __FILE__ \
1094                     " line " __CMK_XSTRING(__LINE__) "."), 0)))
1095 #endif
1096
1097 typedef void (*CmiStartFn)(int argc, char **argv);
1098
1099 /********* CSD - THE SCHEDULER ********
1100   @addtogroup ConverseScheduler
1101   @{
1102 */
1103 CpvExtern(int, _ccd_numchecks);
1104 extern void  CcdCallBacks();
1105 #define CsdPeriodic() do{ if (CpvAccess(_ccd_numchecks)-- <= 0) CcdCallBacks(); } while(0)
1106 #define CsdResetPeriodic()    CpvAccess(_ccd_numchecks) = 0;
1107
1108 extern void  CsdEndIdle(void);
1109 extern void  CsdStillIdle(void);
1110 extern void  CsdBeginIdle(void);
1111
1112 typedef struct {
1113   void *localQ;
1114   Queue nodeQ;
1115   Queue schedQ;
1116   int *localCounter;
1117 #if CMK_OBJECT_QUEUE_AVAILABLE
1118   Queue objQ;
1119 #endif
1120   CmiNodeLock nodeLock;
1121 #if CMK_GRID_QUEUE_AVAILABLE
1122   Queue gridQ;
1123 #endif
1124 #if CMK_SMP && CMK_TASKQUEUE
1125   Queue taskQ;
1126   void *suspendedTaskQ;
1127 #endif
1128 } CsdSchedulerState_t;
1129 extern void CsdSchedulerState_new(CsdSchedulerState_t *state);
1130 extern void *CsdNextMessage(CsdSchedulerState_t *state);
1131 extern void *CsdNextLocalNodeMessage(CsdSchedulerState_t *state);
1132
1133 extern void  *CmiGetNonLocal(void);
1134 extern void   CmiNotifyIdle(void);
1135
1136 /*Different kinds of schedulers: generic, eternal, counting, polling*/
1137 extern  int CsdScheduler(int maxmsgs);
1138 extern void CsdScheduleForever(void);
1139 extern  int CsdScheduleCount(int maxmsgs);
1140 extern void CsdSchedulePoll(void);
1141 extern void CsdScheduleNodePoll(void);
1142
1143 #define CsdExitScheduler()  (CpvAccess(CsdStopFlag)++)
1144 /** @} */
1145
1146 #if CMK_SPANTREE_USE_COMMON_CODE
1147
1148 #define CST_W  (CMK_SPANTREE_MAXSPAN)
1149 #define CST_NN (CmiNumNodes())
1150 #define CmiNodeSpanTreeParent(n) ((n)?(((n)-1)/CST_W):(-1))
1151 #define CmiNodeSpanTreeChildren(n,c) do {\
1152           int _i; \
1153           for(_i=0; _i<CST_W; _i++) { \
1154             int _x = (n)*CST_W+_i+1; \
1155             if(_x<CST_NN) (c)[_i]=_x; \
1156           }\
1157         } while(0)
1158 #define CmiNumNodeSpanTreeChildren(n) ((((n)+1)*CST_W<CST_NN)? CST_W : \
1159           ((((n)*CST_W+1)>=CST_NN)?0:((CST_NN-1)-(n)*CST_W)))
1160 #define CST_R(p) (CmiRankOf(p))
1161 #define CST_NF(n) (CmiNodeFirst(n))
1162 #define CST_SP(n) (CmiNodeSpanTreeParent(n))
1163 #define CST_ND(p) (CmiNodeOf(p))
1164 #define CST_NS(p) (CmiNodeSize(CST_ND(p)))
1165 #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))
1166 #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)))
1167 #define CST_SC(p) (CmiNumNodeSpanTreeChildren(CST_ND(p)))
1168 #define CmiNumSpanTreeChildren(p) (CST_R(p)?CST_C(p):(CST_SC(p)+CST_C(p)))
1169 #define CmiSpanTreeChildren(p,c) do {\
1170           int _i,_c=0; \
1171           if(CST_R(p)==0) { \
1172             for(_i=0;_i<CST_W;_i++) { \
1173               int _x = CST_ND(p)*CST_W+_i+1; \
1174               if(_x<CST_NN) (c)[_c++]=CST_NF(_x); \
1175             }\
1176           } \
1177           for(_i=0;_i<CST_W;_i++) { \
1178             int _x = CST_R(p)*CST_W+_i+1; \
1179             if(_x<CST_NS(p)) (c)[_c++]=CST_NF(CST_ND(p))+_x; \
1180           }\
1181         } while(0)
1182
1183 #else
1184
1185 int      CmiNumSpanTreeChildren(int) ;
1186 int      CmiSpanTreeParent(int) ;
1187 void     CmiSpanTreeChildren(int node, int *children);
1188 int      CmiNumNodeSpanTreeChildren(int);
1189 int      CmiNodeSpanTreeParent(int) ;
1190 void     CmiNodeSpanTreeChildren(int node, int *children) ;
1191 #endif
1192
1193 /****** MULTICAST GROUPS ******/
1194
1195 typedef CMK_MULTICAST_GROUP_TYPE CmiGroup;
1196
1197 void     CmiGroupInit(void);
1198 CmiGroup CmiEstablishGroup(int npes, int *pes);
1199 void     CmiLookupGroup(CmiGroup grp, int *npes, int **pes);
1200
1201 /****** CMI MESSAGE TRANSMISSION ******/
1202
1203 /* Utility function: it packs a multiple chunk message into a singly one.
1204  * Receives the two return values outsize and outdata to return the size of the
1205  * composed message and the message itself. It receives the number of chunks to
1206  * compact, their sizes and datas. The types of the parameters are:
1207  *
1208  * int outsize, inndata, insizes;
1209  * char *outdata;
1210  * char **indatas;
1211  *
1212  * If inndata is negative, it means that the messages need to be copied together
1213  * with their memory header at the beginning (message nesting), and padded to 8
1214  * bytes. The first message never has its memory header attached (it uses the
1215  * one of the new message).
1216  */
1217
1218 #define VECTOR_COMPACT(outsize,outdata,inndata,insizes,indatas,chunkHeaderSize) {\
1219   int i;\
1220   char *tmp;\
1221   outsize=0;\
1222   if (inndata>=0) for(i=0; i<inndata; ++i) outsize += insizes[i];\
1223   else {\
1224     for(i=0; i<-inndata; ++i) outsize += ALIGN_DEFAULT(insizes[i]);\
1225     outsize -= (inndata+1) * chunkHeaderSize;\
1226   }\
1227   outdata = (char *)CmiAlloc(outsize);\
1228   if (!outdata) fprintf(stderr, "%d: Out of mem\n", CmiMyNode());\
1229   tmp = outdata;\
1230   if (inndata>=0) {\
1231     for (i=0; i<inndata; ++i) {\
1232       memcpy(tmp, indatas[i], insizes[i]);\
1233       tmp += insizes[i];\
1234     }\
1235   } else {\
1236     memcpy(tmp, indatas[0], insizes[0]);\
1237     tmp += ALIGN_DEFAULT(insizes[0]);\
1238     for (i=0; i<-inndata; ++i) {\
1239       memcpy(tmp, indatas[i]-chunkHeaderSize, insizes[i]+chunkHeaderSize);\
1240       tmp += ALIGN_DEFAULT(insizes[i])+chunkHeaderSize;\
1241     }\
1242   }\
1243 }
1244
1245 void CmiPushPE(int, void*);
1246 #if CMK_OMP
1247 void          CmiSuspendedTaskEnqueue(int targetRank, void *msg);
1248 void      *   CmiSuspendedTaskPop();
1249 #endif
1250 void          CmiSyncSendFn(int, int, char *);
1251 CmiCommHandle CmiAsyncSendFn(int, int, char *);
1252 void          CmiFreeSendFn(int, int, char *);
1253
1254 void          CmiSyncBroadcastFn(int, char *);
1255 CmiCommHandle CmiAsyncBroadcastFn(int, char *);
1256 void          CmiFreeBroadcastFn(int, char *);
1257
1258 void          CmiSyncBroadcastAllFn(int, char *);
1259 CmiCommHandle CmiAsyncBroadcastAllFn(int, char *);
1260 void          CmiFreeBroadcastAllFn(int, char *);
1261
1262 void          CmiSyncListSendFn(int, int *, int, char*);
1263 CmiCommHandle CmiAsyncListSendFn(int, int *, int, char*);
1264 void          CmiFreeListSendFn(int, int *, int, char*);
1265 void          CmiFreeNodeListSendFn(int, int *, int, char*);
1266
1267 void          CmiSyncMulticastFn(CmiGroup, int, char*);
1268 CmiCommHandle CmiAsyncMulticastFn(CmiGroup, int, char*);
1269 void          CmiFreeMulticastFn(CmiGroup, int, char*);
1270
1271 /* inter partition send counterparts */
1272 void          CmiInterSyncSendFn(int, int, int, char *);
1273 void          CmiInterFreeSendFn(int, int, int, char *);
1274
1275 typedef void * (*CmiReduceMergeFn)(int*,void*,void**,int);
1276 typedef void (*CmiReducePupFn)(void*,void*);
1277 typedef void (*CmiReduceDeleteFn)(void*);
1278
1279 typedef struct {
1280   void *localData;
1281   char **remoteData;
1282   int localSize;
1283   short int numRemoteReceived;
1284   short int numChildren;
1285   int parent;
1286   CmiUInt2 seqID;
1287   char localContributed;
1288   struct {
1289     CmiHandler destination;
1290     CmiReduceMergeFn mergeFn;
1291     CmiReducePupFn pupFn;
1292     CmiReduceDeleteFn deleteFn;
1293   } ops;
1294 } CmiReduction;
1295
1296 typedef CmiUInt2 CmiReductionID;
1297
1298 void * CmiReduceMergeFn_random(int*, void*, void**, int);
1299
1300 void CmiReduce(void *msg, int size, CmiReduceMergeFn mergeFn);
1301 void CmiReduceStruct(void *data, CmiReducePupFn pupFn,
1302                      CmiReduceMergeFn mergeFn, CmiHandler dest,
1303                      CmiReduceDeleteFn deleteFn);
1304 void CmiReduceID(void *msg, int size, CmiReduceMergeFn mergeFn, CmiReductionID id);
1305 void CmiReduceStructID(void *data, CmiReducePupFn pupFn,
1306                      CmiReduceMergeFn mergeFn, CmiHandler dest,
1307                      CmiReduceDeleteFn deleteFn, CmiReductionID id);
1308 void CmiListReduce(int npes, int *pes, void *msg, int size, CmiReduceMergeFn mergeFn, CmiReductionID id);
1309 void CmiListReduceStruct(int npes, int *pes,
1310                      void *data, CmiReducePupFn pupFn,
1311                      CmiReduceMergeFn mergeFn, CmiHandler dest,
1312                      CmiReduceDeleteFn deleteFn, CmiReductionID id);
1313 void CmiGroupReduce(CmiGroup grp, void *msg, int size, CmiReduceMergeFn mergeFn, CmiReductionID id);
1314 void CmiGroupReduceStruct(CmiGroup grp, void *data, CmiReducePupFn pupFn,
1315                      CmiReduceMergeFn mergeFn, CmiHandler dest,
1316                      CmiReduceDeleteFn deleteFn, CmiReductionID id);
1317 void CmiNodeReduce(void *msg, int size, CmiReduceMergeFn mergeFn, int, int, int);
1318 void CmiNodeReduceStruct(void *data, CmiReducePupFn pupFn,
1319                          CmiReduceMergeFn mergeFn, CmiHandler dest,
1320                          CmiReduceDeleteFn deleteFn);
1321 int CmiGetReductionHandler(void);
1322 CmiHandler CmiGetReductionDestination(void);
1323 CmiReductionID CmiGetGlobalReduction(void);
1324 CmiReductionID CmiGetDynamicReduction(void);
1325 void CmiGetDynamicReductionRemote(int handlerIdx, int pe, int dataSize, void *data);
1326
1327 void CmiResetGlobalReduceSeqID(void);
1328
1329 /* If the second parameter (the number of chunks to send) is negative, then
1330  * every message will be started aligned with 8 bytes, and a message header will
1331  * be preponed to every message (message nesting), except the first one which
1332  * uses that of the entire message.
1333  */
1334 void          CmiSyncVectorSend(int, int, int *, char **);
1335 CmiCommHandle CmiAsyncVectorSend(int, int, int *, char **);
1336 void          CmiSyncVectorSendAndFree(int, int, int *, char **);
1337
1338 void          CmiMultipleSend(unsigned int, int, int *, char **);
1339 void          CmiMultipleIsend(unsigned int, int, int *, char **);
1340
1341 int           CmiAsyncMsgSent(CmiCommHandle);
1342 void          CmiReleaseCommHandle(CmiCommHandle);
1343
1344 #define CmiSyncSend(p,s,m)              (CmiSyncSendFn((p),(s),(char *)(m)))
1345 #define CmiAsyncSend(p,s,m)             (CmiAsyncSendFn((p),(s),(char *)(m)))
1346 #define CmiSyncSendAndFree(p,s,m)       (CmiFreeSendFn((p),(s),(char *)(m)))
1347
1348 #define CmiSyncBroadcast(s,m)           (CmiSyncBroadcastFn((s),(char *)(m)))
1349 #define CmiAsyncBroadcast(s,m)          (CmiAsyncBroadcastFn((s),(char *)(m)))
1350 #define CmiSyncBroadcastAndFree(s,m)    (CmiFreeBroadcastFn((s),(char *)(m)))
1351
1352 #define CmiSyncBroadcastAll(s,m)        (CmiSyncBroadcastAllFn((s),(char *)(m)))
1353 #define CmiAsyncBroadcastAll(s,m)       (CmiAsyncBroadcastAllFn((s),(char *)(m)))
1354 #define CmiSyncBroadcastAllAndFree(s,m) (CmiFreeBroadcastAllFn((s),(char *)(m)))
1355
1356 #define CmiSyncListSend(n,l,s,m)        (CmiSyncListSendFn((n),(l),(s),(char *)(m)))
1357 #define CmiAsyncListSend(n,l,s,m)       (CmiAsyncListSendFn((n),(l),(s),(char *)(m)))
1358 #define CmiSyncListSendAndFree(n,l,s,m) (CmiFreeListSendFn((n),(l),(s),(char *)(m)))
1359
1360 #define CmiSyncMulticast(g,s,m)         (CmiSyncMulticastFn((g),(s),(char*)(m)))
1361 #define CmiAsyncMulticast(g,s,m)        (CmiAsyncMulticastFn((g),(s),(char*)(m)))
1362 #define CmiSyncMulticastAndFree(g,s,m)  (CmiFreeMulticastFn((g),(s),(char*)(m)))
1363
1364
1365 /* adding functions for inter-partition communication - only the sync ones because */
1366 /* we do not use the async ones */
1367 #if CMK_HAS_PARTITION
1368 #define CmiInterSyncSend(pe,p,s,m)              (CmiInterSyncSendFn((pe),(p),(s),(char *)(m)))
1369 #define CmiInterSyncSendAndFree(pe,p,s,m)       (CmiInterFreeSendFn((pe),(p),(s),(char *)(m)))
1370 #else
1371 #define CmiInterSyncSend(pe,p,s,m)              (CmiSyncSendFn((pe),(s),(char *)(m)))
1372 #define CmiInterSyncSendAndFree(pe,p,s,m)       (CmiFreeSendFn((pe),(s),(char *)(m)))
1373 #endif
1374
1375 /* support for rest may come later if required */
1376
1377 #if CMK_NODE_QUEUE_AVAILABLE
1378 void          CmiSyncNodeSendFn(int, int, char *);
1379 CmiCommHandle CmiAsyncNodeSendFn(int, int, char *);
1380 void          CmiFreeNodeSendFn(int, int, char *);
1381
1382 void          CmiSyncNodeBroadcastFn(int, char *);
1383 CmiCommHandle CmiAsyncNodeBroadcastFn(int, char *);
1384 void          CmiFreeNodeBroadcastFn(int, char *);
1385
1386 void          CmiSyncNodeBroadcastAllFn(int, char *);
1387 CmiCommHandle CmiAsyncNodeBroadcastAllFn(int, char *);
1388 void          CmiFreeNodeBroadcastAllFn(int, char *);
1389
1390 /* if node queue is available, adding inter partition counterparts */
1391 void          CmiInterSyncNodeSendFn(int, int, int, char *);
1392 void          CmiInterFreeNodeSendFn(int, int, int, char *);
1393 #endif
1394
1395 #if CMK_NODE_QUEUE_AVAILABLE
1396 #define CmiSyncNodeSend(p,s,m)          (CmiSyncNodeSendFn((p),(s),(char *)(m)))
1397 #define CmiAsyncNodeSend(p,s,m)             (CmiAsyncNodeSendFn((p),(s),(char *)(m)))
1398 #define CmiSyncNodeSendAndFree(p,s,m)       (CmiFreeNodeSendFn((p),(s),(char *)(m)))
1399 #define CmiSyncNodeBroadcast(s,m)           (CmiSyncNodeBroadcastFn((s),(char *)(m)))
1400 #define CmiAsyncNodeBroadcast(s,m)          (CmiAsyncNodeBroadcastFn((s),(char *)(m)))
1401 #define CmiSyncNodeBroadcastAndFree(s,m)    (CmiFreeNodeBroadcastFn((s),(char *)(m)))
1402 #define CmiSyncNodeBroadcastAll(s,m)        (CmiSyncNodeBroadcastAllFn((s),(char *)(m)))
1403 #define CmiAsyncNodeBroadcastAll(s,m)       (CmiAsyncNodeBroadcastAllFn((s),(char *)(m)))
1404 #define CmiSyncNodeBroadcastAllAndFree(s,m) (CmiFreeNodeBroadcastAllFn((s),(char *)(m)))
1405
1406 /* counterparts of inter partition */
1407 #if CMK_HAS_PARTITION
1408 #define CmiInterSyncNodeSend(pe,p,s,m)         (CmiInterSyncNodeSendFn((pe),(p),(s),(char *)(m)))
1409 #define CmiInterSyncNodeSendAndFree(pe,p,s,m)  (CmiInterFreeNodeSendFn((pe),(p),(s),(char *)(m)))
1410 #else 
1411 #define CmiInterSyncNodeSend(pe,p,s,m)         (CmiSyncNodeSendFn((pe),(s),(char *)(m)))
1412 #define CmiInterSyncNodeSendAndFree(pe,p,s,m)  (CmiFreeNodeSendFn((pe),(s),(char *)(m)))
1413 #endif
1414
1415 #else
1416
1417 #define CmiSyncNodeSend(n,s,m)        CmiSyncSend(CmiNodeFirst(n),s,m)
1418 #define CmiAsyncNodeSend(n,s,m)       CmiAsyncSend(CmiNodeFirst(n),s,m)
1419 #define CmiSyncNodeSendAndFree(n,s,m) CmiSyncSendAndFree(CmiNodeFirst(n),s,m)
1420 #if CMK_UTH_VERSION || CMK_MULTICORE
1421 #define CmiSyncNodeBroadcast(s,m)           do { \
1422           int _i; \
1423           for(_i=0; _i<CmiNumNodes(); _i++) \
1424             if(_i != CmiMyNode()) \
1425               CmiSyncSend(CmiNodeFirst(_i),s,m); \
1426         } while(0)
1427 #define CmiAsyncNodeBroadcast(s,m)          CmiSyncNodeBroadcast(s,m)
1428 #define CmiSyncNodeBroadcastAndFree(s,m)    do { \
1429           CmiSyncNodeBroadcast(s,m); \
1430           CmiFree(m); \
1431         } while(0)
1432 #define CmiSyncNodeBroadcastAll(s,m)           do { \
1433           int _i; \
1434           for(_i=0; _i<CmiNumNodes(); _i++) \
1435             CmiSyncSend(CmiNodeFirst(_i),s,m); \
1436         } while(0)
1437 #define CmiAsyncNodeBroadcastAll(s,m)       CmiSyncNodeBroadcastAll(s,m)
1438 #define CmiSyncNodeBroadcastAllAndFree(s,m) do { \
1439           CmiSyncNodeBroadcastAll(s,m); \
1440           CmiFree(m); \
1441         } while(0)
1442 #else
1443 #define CmiSyncNodeBroadcast(s,m)           CmiSyncBroadcast(s,m)
1444 #define CmiAsyncNodeBroadcast(s,m)          CmiAsyncBroadcast(s,m)
1445 #define CmiSyncNodeBroadcastAndFree(s,m)    CmiSyncBroadcastAndFree(s,m)
1446 #define CmiSyncNodeBroadcastAll(s,m)        CmiSyncBroadcastAll(s,m)
1447 #define CmiAsyncNodeBroadcastAll(s,m)       CmiAsyncBroadcastAll(s,m)
1448 #define CmiSyncNodeBroadcastAllAndFree(s,m) CmiSyncBroadcastAllAndFree(s,m)
1449 #endif
1450 /* and the inter partition counterparts */
1451 #if CMK_HAS_PARTITION
1452 #define CmiInterSyncNodeSend(n,p,s,m)          CmiInterSyncSend(CmiNodeFirst(n),p,s,m)
1453 #define CmiInterSyncNodeSendAndFree(n,p,s,m)   CmiInterSyncSendAndFree(CmiNodeFirst(n),p,s,m)
1454 #else
1455 #define CmiInterSyncNodeSend(n,p,s,m)          CmiSyncSend(CmiNodeFirst(n),s,m)
1456 #define CmiInterSyncNodeSendAndFree(n,p,s,m)   CmiSyncSendAndFree(CmiNodeFirst(n),s,m)
1457 #endif
1458 #endif
1459
1460 /******** CMI MESSAGE RECEPTION ********/
1461
1462 void   CmiDeliversInit();
1463 int    CmiDeliverMsgs(int maxmsgs);
1464 void   CmiDeliverSpecificMsg(int handler);
1465 void   CmiHandleMessage(void *msg);
1466
1467 /******** CQS: THE QUEUEING SYSTEM ********
1468  * @addtogroup CharmScheduler
1469  * @{ 
1470  */
1471 #define CQS_QUEUEING_FIFO 2
1472 #define CQS_QUEUEING_LIFO 3
1473 #define CQS_QUEUEING_IFIFO 4
1474 #define CQS_QUEUEING_ILIFO 5
1475 #define CQS_QUEUEING_BFIFO 6
1476 #define CQS_QUEUEING_BLIFO 7
1477 #define CQS_QUEUEING_LFIFO 8
1478 #define CQS_QUEUEING_LLIFO 9
1479 /** @} */
1480
1481
1482 /****** CTH: THE LOW-LEVEL THREADS PACKAGE ******/
1483
1484 typedef struct CthThreadStruct *CthThread;
1485 typedef struct {
1486   /*Start with a message header so threads can be enqueued 
1487     as messages (e.g., by CthEnqueueNormalThread in convcore.C)
1488   */
1489   char cmicore[CmiReservedHeaderSize];
1490   CthThread thread;
1491   int serialNo;
1492 } CthThreadToken;
1493
1494 CthThreadToken *CthGetToken(CthThread);
1495
1496 typedef void        (*CthVoidFn)(void *);
1497 typedef void        (*CthAwkFn)(CthThreadToken *,int,
1498                                 int prioBits,unsigned int *prioptr);
1499 typedef CthThread   (*CthThFn)(void);
1500
1501 void       CthSetSerialNo(CthThread t, int no);
1502 int        CthImplemented(void);
1503
1504 int        CthMigratable(void);
1505 CthThread  CthPup(pup_er, CthThread);
1506
1507 CthThread  CthSelf(void);
1508 CthThread  CthCreate(CthVoidFn, void *, int);
1509 CthThread  CthCreateMigratable(CthVoidFn, void *, int);
1510 void       CthResume(CthThread);
1511 void       CthFree(CthThread);
1512
1513 void       CthSetSuspendable(CthThread, int);
1514 int        CthIsSuspendable(CthThread);
1515
1516 /* added for bigsim out-of-core emulation */
1517 void       CthPrintThdMagic(CthThread); 
1518 void       CthPrintThdStack(CthThread);
1519
1520 void       CthSuspend(void);
1521 void       CthAwaken(CthThread);
1522 void       CthAwakenPrio(CthThread, int, int, unsigned int *);
1523 void       CthSetStrategy(CthThread, CthAwkFn, CthThFn);
1524 void       CthSetStrategyDefault(CthThread);
1525 #if CMK_OMP
1526 void       CthSetStrategyWorkStealing(CthThread);
1527 void       CthSetStrategySuspendedWorkStealing(CthThread);
1528 int        CthScheduled(CthThread t);
1529 void       CthScheduledDecrement();
1530 CthThread  CthGetCurrentThread();
1531 CpvExtern(int, prevGtid);
1532 void       CthSetPrev(CthThread t, CthThread prev);
1533 #endif
1534 void       CthYield(void);
1535 void       CthYieldPrio(int,int,unsigned int*);
1536
1537 void       CthSetNext(CthThread t, CthThread next);
1538 CthThread  CthGetNext(CthThread t);
1539 #if CMK_TRACE_ENABLED
1540 void CthSetEventInfo(CthThread t, int event, int srcPE);
1541 #endif
1542 void       CthSwitchThread(CthThread t);
1543
1544 size_t     CthStackOffset(CthThread t, char *p);
1545 char     * CthPointer(CthThread t, size_t pos);
1546
1547 /* unimplemented: preemptive threads */
1548 void       CthAutoYield(CthThread t, int flag);
1549 double     CthAutoYieldFreq(CthThread t);
1550 void       CthAutoYieldBlock(void);
1551 void       CthAutoYieldUnblock(void);
1552
1553 /* Converse Thread Global (Ctg) global variable manipulation */
1554 typedef struct CtgGlobalStruct *CtgGlobals;
1555
1556 /** Initialize the globals support (called on each processor). */
1557 void CtgInit(void);
1558
1559 /** PIC method used. **/
1560 #define CMI_PIC_NOP     0
1561 #define CMI_PIC_ELFGOT  1
1562 CpvExtern(int, CmiPICMethod);
1563
1564 /** Copy the current globals into this new set */
1565 CtgGlobals CtgCreate(CthThread tid);
1566 /** Install this set of globals. If g==NULL, returns to original globals. */
1567 void CtgInstall(CtgGlobals g);
1568 /** PUP this (not currently installed) globals set */
1569 CtgGlobals CtgPup(pup_er, CtgGlobals g);
1570 /** Delete this (not currently installed) set of globals. */
1571 void CtgFree(CtgGlobals g);
1572 /** Return the current global list */
1573 CtgGlobals CtgCurrentGlobals(void);
1574
1575 /** for TLS globals */
1576 void CtgInstallTLS(void *cur, void *next);
1577 void CtgInstallMainThreadTLS(void *cur);
1578 void CtgInstallCthTLS(void *cur, void *next);
1579 void CmiEnableTLS(void);
1580 void CmiDisableTLS(void);
1581
1582 /* The thread listener structure. The user must register one such listener
1583         if he wants to find out when a thread is suspended or when it starts running
1584         or gets destroyed. It can be used for tracing etc.
1585 */
1586
1587 struct CthThreadListener;
1588
1589 typedef void (*CthThreadListener_suspend)(struct CthThreadListener *l);
1590 typedef void (*CthThreadListener_resume)(struct CthThreadListener *l);
1591 typedef void (*CthThreadListener_free)(struct CthThreadListener *l);
1592
1593 struct CthThreadListener {
1594        /** This thread is about to block. */
1595        CthThreadListener_suspend suspend;
1596
1597        /** This thread is about to begin execution after blocking. */
1598        CthThreadListener_resume resume;
1599
1600        /** This thread is being destroyed.  */
1601        CthThreadListener_free free;
1602
1603        /** Pointer to listener-specific data (if needed).
1604            Set by listener.
1605        */
1606        void *data;
1607
1608        /** Pointer to the thread this listener controls.
1609            Set by CthAddListener.
1610         */
1611        CthThread thread;
1612
1613        /** The next listener, or NULL at end of chain.
1614            Set by CthAddListener, and used only by threads.c.
1615        */
1616        struct CthThreadListener *next;
1617 };
1618
1619 /**
1620   This listener is about to begin receiving suspend and
1621 resume events for this thread.  "suspend", "resume", "free",
1622 and "data" fields must all already be set.  When this thread
1623 exits, l->free will be called on this listener, which should
1624 deallocate the listener memory.
1625 */
1626 void CthAddListener(CthThread th,struct CthThreadListener *l);
1627
1628 /**
1629   This is function is inserted into .def.h after thread creation.
1630   It serves as an interface for the user to add the listeners 
1631   as needed. User has to implement this somewhere in the system.
1632 */
1633 void CthUserAddListeners(CthThread th);
1634
1635 /****** CTH: THREAD-PRIVATE VARIABLES ******/
1636
1637 #if CMK_THREADS_REQUIRE_NO_CPV
1638
1639 #define CthCpvDeclare(t,v)    t v
1640 #define CthCpvExtern(t,v)     extern t v
1641 #define CthCpvStatic(t,v)     static t v
1642 #define CthCpvInitialize(t,v) do {} while(0)
1643 #define CthCpvAccess(x)       x
1644
1645 #else
1646
1647 #define CthCpvDeclare(t,v)    CpvDeclare(t,v)
1648 #define CthCpvExtern(t,v)     CpvExtern(t,v)
1649 #define CthCpvStatic(t,v)     CpvStaticDeclare(t,v)
1650 #define CthCpvInitialize(t,v) CpvInitialize(t,v)
1651 #define CthCpvAccess(x)       CpvAccess(x)
1652
1653 #endif
1654
1655 CthCpvExtern(char *,CthData);
1656 extern size_t CthRegister(size_t dataSize);
1657 extern void CthRegistered(size_t dataOffMax);
1658 extern char *CthGetData(CthThread t);
1659
1660 #define CtvDeclare(t,v)         typedef t CtvType##v; CsvDeclare(int,CtvOffs##v)=(-1)
1661 #define CtvStaticDeclare(t,v)   typedef t CtvType##v; CsvStaticDeclare(int,CtvOffs##v)=(-1)
1662 #define CtvExtern(t,v)          typedef t CtvType##v; CsvExtern(int,CtvOffs##v)
1663 #define CtvAccess(v)            (*((CtvType##v *)(CthCpvAccess(CthData)+CsvAccess(CtvOffs##v))))
1664 #define CtvAccessOther(t,v)            (*((CtvType##v *)(CthGetData(t)+CsvAccess(CtvOffs##v))))
1665 #define CtvInitialize(t,v)      do { \
1666         if(CsvAccess(CtvOffs##v)==(-1)) \
1667                 CsvAccess(CtvOffs##v)=CthRegister(sizeof(CtvType##v));\
1668         else CthRegistered(CsvAccess(CtvOffs##v)+sizeof(CtvType##v));\
1669 } while(0)
1670
1671 #define CtvInitialized(v) (CsvAccess(CtvOffs##v)!=(-1))
1672
1673 /****** CFUTURE: CONVERSE FUTURES ******/
1674
1675 typedef struct Cfuture_s
1676 {
1677   int pe;
1678   struct Cfuture_data_s *data;
1679 }
1680 Cfuture;
1681
1682 #define CfutureValueData(v) ((void*)((v)->rest))
1683
1684 Cfuture       CfutureCreate(void);
1685 void          CfutureSet(Cfuture f, void *val, int len);
1686 void         *CfutureWait(Cfuture f);
1687 void          CfutureDestroy(Cfuture f);
1688
1689 void         *CfutureCreateBuffer(int bytes);
1690 void          CfutureDestroyBuffer(void *val);
1691 void          CfutureStoreBuffer(Cfuture f, void *value);
1692
1693 #define       CfuturePE(f) ((f).pe)
1694
1695 void CfutureInit(void);
1696
1697 /****** CLD: THE LOAD BALANCER ******/
1698
1699 #define CLD_ANYWHERE (-1)
1700 #define CLD_BROADCAST (-2)
1701 #define CLD_BROADCAST_ALL (-3)
1702
1703 typedef void (*CldPackFn)(void *msg);
1704
1705 typedef void (*CldInfoFn)(void *msg, 
1706                           CldPackFn *packer,
1707                           int *len,
1708                           int *queueing,
1709                           int *priobits, 
1710                           unsigned int **prioptr);
1711
1712 typedef int (*CldEstimator)(void);
1713
1714 int CldRegisterInfoFn(CldInfoFn fn);
1715 int CldRegisterPackFn(CldPackFn fn);
1716 void CldRegisterEstimator(CldEstimator fn);
1717 int CldEstimate(void);
1718 const char *CldGetStrategy(void);
1719
1720 void CldEnqueue(int pe, void *msg, int infofn);
1721 void CldEnqueueMulti(int npes, int *pes, void *msg, int infofn);
1722 void CldEnqueueGroup(CmiGroup grp, void *msg, int infofn);
1723 void CldNodeEnqueue(int node, void *msg, int infofn);
1724
1725 /****** CMM: THE MESSAGE MANAGER ******/
1726
1727 typedef struct CmmTableStruct *CmmTable;
1728
1729 #define CmmWildCard (-1)
1730
1731 typedef void (*CmmPupMessageFn)(pup_er p,void **msg);
1732 CmmTable CmmPup(pup_er p, CmmTable t, CmmPupMessageFn msgpup);
1733
1734 CmmTable   CmmNew();
1735 void       CmmFree(CmmTable t);
1736 void       CmmFreeAll(CmmTable t);
1737 void       CmmPut(CmmTable t, int ntags, int *tags, void *msg);
1738 void      *CmmFind(CmmTable t, int ntags, int *tags, int *returntags, int del);
1739 int        CmmEntries(CmmTable t);
1740 int        CmmGetLastTag(CmmTable t, int ntags, int *tags);
1741 #define    CmmGet(t,nt,tg,rt)   (CmmFind((t),(nt),(tg),(rt),1))
1742 #define    CmmProbe(t,nt,tg,rt) (CmmFind((t),(nt),(tg),(rt),0))
1743
1744 /******** ConverseInit and ConverseExit ********/
1745
1746 void ConverseInit(int, char**, CmiStartFn, int, int);
1747
1748 /* Optional parameter for ConverseExit() - based on
1749 https://stackoverflow.com/a/28074198/1250282 */
1750
1751 void realConverseExit(int exitcode);
1752
1753 #define CONVEXIT_1(x) realConverseExit(x)
1754 #define CONVEXIT_0() CONVEXIT_1(0) /* Default ConverseExit() exit code: 0 */
1755
1756 #define CONV_FUNC_CHOOSER(_f1, _f2, _f3, ...) _f3
1757 #define CONV_FUNC_RECOMPOSER(argsWithParentheses) CONV_FUNC_CHOOSER argsWithParentheses
1758 #define CONV_CHOOSE_FROM_ARG_COUNT(...) CONV_FUNC_RECOMPOSER((__VA_ARGS__, CONVEXIT_2, CONVEXIT_1, ))
1759 #define CONV_NO_ARG_EXPANDER() ,,CONVEXIT_0
1760 #define CONV_MACRO_CHOOSER(...) CONV_CHOOSE_FROM_ARG_COUNT(CONV_NO_ARG_EXPANDER __VA_ARGS__ ())
1761 #define ConverseExit(...) CONV_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
1762
1763
1764 #if CMK_SHRINK_EXPAND
1765 void ConverseCleanup(void);
1766 #endif
1767 CMK_NORETURN void CmiAbort(const char *);
1768 void CmiOutOfMemory(int nBytes);
1769
1770 #if CMK_MEMCHECK_OFF
1771 #define _MEMCHECK(p) do{}while(0)
1772 #else
1773 #define _MEMCHECK(p) do { \
1774                          if ((p)==0) CmiOutOfMemory(-1);\
1775                      } while(0)
1776 #endif
1777
1778 /******** CONVCONDS ********/
1779
1780 typedef void (*CcdVoidFn)(void *userParam,double curWallTime);
1781
1782 /*CPU conditions*/
1783 #define CcdPROCESSOR_BEGIN_BUSY 0
1784 #define CcdPROCESSOR_END_IDLE 0 /*Synonym*/
1785 #define CcdPROCESSOR_BEGIN_IDLE 1
1786 #define CcdPROCESSOR_END_BUSY 1 /*Synonym*/
1787 #define CcdPROCESSOR_STILL_IDLE 2
1788
1789 /*Periodic calls*/
1790 #define CcdPERIODIC           3 /*every few ms*/
1791 #define CcdPERIODIC_10ms      4 /*every 10ms (100Hz)*/
1792 #define CcdPERIODIC_100ms     5 /*every 100ms (10Hz)*/
1793 #define CcdPERIODIC_1second   6 /*every second*/
1794 #define CcdPERIODIC_1s        6 /*every second*/
1795 #define CcdPERIODIC_5s        7 /*every second*/
1796 #define CcdPERIODIC_5seconds  7 /*every second*/
1797 #define CcdPERIODIC_10second  8 /*every 10 seconds*/
1798 #define CcdPERIODIC_10seconds 8 /*every 10 seconds*/
1799 #define CcdPERIODIC_10s       8 /*every 10 seconds*/
1800 #define CcdPERIODIC_1minute   9 /*every minute*/
1801 #define CcdPERIODIC_2minute  10 /*every 2 minute*/
1802 #define CcdPERIODIC_5minute  11 /*every 5 minute*/
1803 #define CcdPERIODIC_10minute 12 /*every 10 minutes*/
1804 #define CcdPERIODIC_1hour    13 /*every hour*/
1805 #define CcdPERIODIC_12hour   14 /*every 12 hours*/
1806 #define CcdPERIODIC_1day     15 /*every day*/
1807
1808 /*Other conditions*/
1809 #define CcdQUIESCENCE        16
1810 #define CcdTOPOLOGY_AVAIL    17
1811 #define CcdSIGUSR1           18
1812 #define CcdSIGUSR2           19
1813
1814 /*User-defined conditions start here*/
1815 #define CcdUSER              20
1816
1817 /*User-defined conditions end here*/
1818 /*Conditionally defined so users can build with larger CcdUSERMAX values*/
1819 #ifndef CcdUSERMAX
1820 #define CcdUSERMAX          127
1821 #endif
1822
1823 #define CcdIGNOREPE   -2
1824 #if CMK_CONDS_USE_SPECIAL_CODE
1825 typedef int (*CmiSwitchToPEFnPtr)(int pe);
1826 extern CmiSwitchToPEFnPtr CmiSwitchToPE;
1827 #else
1828 #define CmiSwitchToPE(pe)  pe
1829 #endif
1830 void CcdCallFnAfter(CcdVoidFn fnp, void *arg, double msecs);
1831 int CcdCallOnCondition(int condnum, CcdVoidFn fnp, void *arg);
1832 int CcdCallOnConditionKeep(int condnum, CcdVoidFn fnp, void *arg);
1833 void CcdCallFnAfterOnPE(CcdVoidFn fnp, void *arg, double msecs, int pe);
1834 int CcdCallOnConditionOnPE(int condnum, CcdVoidFn fnp, void *arg, int pe);
1835 int CcdCallOnConditionKeepOnPE(int condnum, CcdVoidFn fnp, void *arg, int pe);
1836 void CcdCancelCallOnCondition(int condnum, int idx);
1837 void CcdCancelCallOnConditionKeep(int condnum, int idx);
1838 void CcdRaiseCondition(int condnum);
1839 double CcdSetResolution(double newResolution);
1840 double CcdResetResolution(void);
1841 double CcdIncreaseResolution(double newResolution);
1842
1843 /* Command-Line-Argument handling */
1844 void CmiArgGroup(const char *parentName,const char *groupName);
1845 int CmiGetArgInt(char **argv,const char *arg,int *optDest);
1846 int CmiGetArgIntDesc(char **argv,const char *arg,int *optDest,const char *desc);
1847 int CmiGetArgLong(char **argv,const char *arg,CmiInt8 *optDest);
1848 int CmiGetArgLongDesc(char **argv,const char *arg,CmiInt8 *optDest,const char *desc);
1849 int CmiGetArgDouble(char **argv,const char *arg,double *optDest);
1850 int CmiGetArgDoubleDesc(char **argv,const char *arg,double *optDest,const char *desc);
1851 int CmiGetArgString(char **argv,const char *arg,char **optDest);
1852 int CmiGetArgStringDesc(char **argv,const char *arg,char **optDest,const char *desc);
1853 int CmiGetArgFlag(char **argv,const char *arg);
1854 int CmiGetArgFlagDesc(char **argv,const char *arg,const char *desc);
1855 void CmiDeleteArgs(char **argv,int k);
1856 int CmiGetArgc(char **argv);
1857 char **CmiCopyArgs(char **argv);
1858 int CmiArgGivingUsage(void);
1859 void CmiDeprecateArgInt(char **argv,const char *arg,const char *desc,const char *warning);
1860
1861 /** 
1862    Extract the function-return pointers listed in the stack
1863    up to this depth.  nSkip is the number of enclosing functions
1864    to skip-- for example, nSkip==0 means the retPtrs[0]
1865    will be the caller of CmiBacktraceRecord.  
1866    Returns retPtrs[0..*nLevels-1] stack pointers.
1867    *nLevels may be decreased if not enough levels are available.
1868  */
1869 void CmiBacktraceRecord(void **retPtrs,int nSkip,int *nLevels);
1870
1871 /** Look up the names of these function pointers.
1872 Caller must free() the returned array, but not the individual
1873 strings.
1874 */
1875 char **CmiBacktraceLookup(void **srcPtrs,int nLevels);
1876
1877 /** Print out the names of these function pointers. */
1878 void CmiBacktracePrint(void **retPtrs,int nLevels);
1879
1880 /* Print (to stdout) the names of the functions that have been 
1881    called up to this point. nSkip is the number of routines on the
1882    top of the stack to *not* print out. */
1883 void CmiPrintStackTrace(int nSkip);
1884 int CmiIsFortranLibraryCall(void);
1885
1886 #if CMK_CMIDELIVERS_USE_COMMON_CODE
1887 CpvExtern(void*, CmiLocalQueue);
1888 #endif
1889
1890 char *CmiCopyMsg(char *msg, int len);
1891
1892 /******** Hypercube broadcast propagation (Binomial tree) ********/
1893
1894 /*
1895   This routing will receive a number k containing the dimension in the hypercube
1896   to be used for the broadcast, i.e. k=0 means sending only to MyPe^1, k=1 means
1897   sending to MyPe^2 and MyPe^1, etc.
1898   The array dest_pes will be filled with the id of the processors to which send,
1899   it has to be already allocated, the size should be at least k+1 to allow
1900   enough space.
1901   It return the number of processors to which send, i.e. the size of dest_pes.
1902   This may be less than k+1 due to not complete hypercubes.
1903   For example with pow(2,n)+2 procs and 0 broadcasting, proc pow(2,n) will
1904   receive from 0 in the first step but then it has only proc pow(2,n)+1 as
1905   destination, so most of the other dimentions will be skipped.
1906 */
1907 int HypercubeGetBcastDestinations(int mype, int total_pes, int k, int *dest_pes);
1908
1909 /******** Immediate Messages ********/
1910
1911 CpvExtern(int, CmiImmediateMsgHandlerIdx);
1912
1913
1914 CpvExtern(unsigned, networkProgressCount);
1915 extern int networkProgressPeriod;
1916
1917 #if !CMK_MACHINE_PROGRESS_DEFINED
1918
1919 #define CmiNetworkProgress() 
1920 #define CmiNetworkProgressAfter(p) 
1921 #define CmiMachineProgressImpl()
1922
1923 #else
1924
1925 /*#ifdef __cplusplus
1926 extern "C" 
1927 #endif*/
1928 void CmiMachineProgressImpl();
1929
1930 #if CMK_USE_PXSHM
1931 CMI_EXTERNC void CommunicationServerPxshm(void);
1932 #define CmiNetworkProgress() {CpvAccess(networkProgressCount) ++; \
1933       if(CpvAccess(networkProgressCount) >=  networkProgressPeriod) { \
1934           CmiMachineProgressImpl(); \
1935           CommunicationServerPxshm(); \
1936           CpvAccess(networkProgressCount) = 0; \
1937       } \
1938 }
1939 #else
1940 #define CmiNetworkProgress() {CpvAccess(networkProgressCount) ++; \
1941       if(CpvAccess(networkProgressCount) >=  networkProgressPeriod) { \
1942           CmiMachineProgressImpl(); \
1943           CpvAccess(networkProgressCount) = 0; \
1944       } \
1945 }
1946 #endif
1947
1948 #if CMK_USE_PXSHM
1949 #define CmiNetworkProgressAfter(p) {CpvAccess(networkProgressCount) ++; \
1950       if(CpvAccess(networkProgressCount) >=  p) { \
1951           CmiMachineProgressImpl(); \
1952           CommunicationServerPxshm(); \
1953           CpvAccess(networkProgressCount) = 0; \
1954       } \
1955 }
1956 #else
1957 #define CmiNetworkProgressAfter(p) {CpvAccess(networkProgressCount) ++; \
1958       if(CpvAccess(networkProgressCount) >=  p) { \
1959           CmiMachineProgressImpl(); \
1960           CpvAccess(networkProgressCount) = 0; \
1961       } \
1962 }
1963 #endif
1964
1965 #endif
1966
1967 #define CmiProbeImmediateMsg CmiMachineProgressImpl
1968
1969 /*
1970    to immediate-fy a Converse message, set the most significant bit to 1
1971    in the Converse handler (x|0x8000). 
1972 */
1973 #if CMK_IMMEDIATE_MSG
1974 void CmiDelayImmediate(void);
1975 #  define CmiBecomeImmediate(msg) do { \
1976         CmiSetHandler(msg, (CmiGetHandler(msg))|0x8000); \
1977      } while (0)
1978 #  define CmiResetImmediate(msg) do { \
1979         CmiSetHandler(msg, (CmiGetHandler(msg))&(~0x8000)); \
1980      } while (0)
1981 #  define CmiIsImmediate(msg)      ((CmiGetHandler(msg)) & 0x8000) 
1982 #  define CmiImmediateHandler(msg) ((CmiGetHandler(msg)) ^ 0x8000)
1983 /*
1984 #  define CmiIsImmediate(msg)   ((CmiGetHandler(msg) == CpvAccessOther(CmiImmediateMsgHandlerIdx,0)))
1985 #  define CmiBecomeImmediate(msg) do {\
1986         CmiSetXHandler(msg,CmiGetHandler(msg)); \
1987         CmiSetHandler(msg,CpvAccessOther(CmiImmediateMsgHandlerIdx,0)); \
1988      } while (0)
1989 #  define CmiImemdiateHandler(msg) (CmiGetXHandler(msg))
1990 */
1991 /* 
1992   for non smp and non intr based version, it returns _immRunning
1993   for smp, this doesnot matter - CkMyPe() comparasion normaly fails and
1994            non threadsafe CqsEnqueueGeneral is avoided.
1995 */
1996 #if CMK_NET_VERSION && ! CMK_SMP && ! defined(CMK_CPV_IS_SMP)
1997 extern int _immRunning;
1998 #  define CmiImmIsRunning()        (_immRunning)
1999 #else
2000 #  define CmiImmIsRunning()        (0)
2001 #endif
2002
2003 #else
2004 #  define CmiBecomeImmediate(msg) /* empty */
2005 #  define CmiResetImmediate(msg)  /* empty */
2006 #  define CmiIsImmediate(msg)   (0)
2007 #  define CmiImmIsRunning()       (0)
2008 #endif
2009
2010 /******** Memory Fence ********/
2011
2012 #if  CMK_SMP
2013 /* ImplSelect<num> selects one of two implementations for the atomic operations depending on the number of parameters
2014  * e.g.) CmiMemoryAtomicIncrement(input)
2015  *       -> ImplSelect2(input, CmiMemoryAtomicIncrementMemOrder, CmiMemoryAtomiIncrementSimple) CmiMemoryAtomicIncrementSimple
2016  *       -> __sync_fetch_and_add(&input, 1)
2017  *
2018  *       CmiMemoryAtomicIncrement(input, memory_order_relaxed) (you can specify the memory consistency for each atomic operation with the C11 consistency keywords)
2019  *       -> ImplSelect2(input, memory_order_relaxed, CmiMemoryAtomicIncrementMemOrder, CmiMemoryAtomicIncrementSimple) CmiMemoryAtomicIncrementMemOrder
2020  *       -> __atomic_fetch_and_add(&input, 1, memory_order_relaxed) (if the underlying compiler supports C11)
2021  *       -> CmiMemoryAtomicSimple(input) -> __sync_fetch_and_add(&input, 1) (if the compiler doesn't support C11, the memory consistency keyword ignored)
2022  *                                       -> __asm__ __volatile__("lock incl (%0)" :: "r" (&(someInt))) (CMK_GCC_X86_ASM on)
2023  *                                       -> CmiLock(cmiMemoryLock); someInt=someInt+1; CmiUnlock(cmiMemoryLock); ( Sync primitives and GCC asm not supported)
2024  * */
2025 #define ImplSelect2(_1, _2, NAME, ...) NAME
2026 #define ImplSelect3(_1, _2, _3, NAME, ...) NAME
2027 #define CmiMemoryAtomicIncrement(...) ImplSelect2(__VA_ARGS__, CmiMemoryAtomicIncrementMemOrder, CmiMemoryAtomicIncrementSimple, )(__VA_ARGS__)
2028 #define CmiMemoryAtomicDecrement(...) ImplSelect2(__VA_ARGS__, CmiMemoryAtomicDecrementMemOrder, CmiMemoryAtomicDecrementSimple, )(__VA_ARGS__)
2029 #define CmiMemoryAtomicFetchAndInc(...) ImplSelect3(__VA_ARGS__, CmiMemoryAtomicFetchAndIncMemOrder, CmiMemoryAtomicFetchAndIncSimple, )(__VA_ARGS__)
2030
2031 #if CMK_C_SYNC_ADD_AND_FETCH_PRIMITIVE
2032 #if __GNUC__ && __STDC_VERSION__ >= 201112L && !__STDC_NO_ATOMICS__
2033 #ifndef _STDATOMIC_H
2034 typedef enum
2035   {
2036     memory_order_relaxed = __ATOMIC_RELAXED,
2037     memory_order_consume = __ATOMIC_CONSUME,
2038     memory_order_acquire = __ATOMIC_ACQUIRE,
2039     memory_order_release = __ATOMIC_RELEASE,
2040     memory_order_acq_rel = __ATOMIC_ACQ_REL,
2041     memory_order_seq_cst = __ATOMIC_SEQ_CST
2042   } memory_order;
2043 #endif
2044
2045 #define CmiMemoryAtomicIncrementMemOrder(someInt, MemModel) __atomic_fetch_add(&(someInt),1, MemModel);
2046 #define CmiMemoryAtomicDecrementMemOrder(someInt, MemModel) __atomic_fetch_sub(&(someInt),1, MemModel);
2047 #define CmiMemoryAtomicFetchAndIncMemOrder(input,output, MemModel) (output) = __atomic_fetch_add(&(input),1, MemModel);
2048
2049 #else /* Mem ordering is not supported */
2050 #define CmiMemoryAtomicIncrementMemOrder(someInt, MemModel) CmiMemoryAtomicIncrementSimple(someInt);
2051 #define CmiMemoryAtomicDecrementMemOrder(someInt, MemModel) CmiMemoryAtomicDecrementSimple(someInt);
2052 #define CmiMemoryAtomicFetchAndIncMemOrder(input,output, MemModel) CmiMemoryAtomicFetchAndIncSimple(input, output);
2053 #endif
2054 #define CmiMemoryAtomicIncrementSimple(someInt)    __sync_fetch_and_add(&(someInt), 1)
2055 #define CmiMemoryAtomicDecrementSimple(someInt)    __sync_fetch_and_sub(&(someInt), 1)
2056 #define CmiMemoryAtomicFetchAndIncSimple(input,output)   (output) =__sync_fetch_and_add(&(input), 1)
2057
2058 #else /* !CMK_C_SYNC_ADD_AND_FETCH_PRIMITIVE */
2059 #define CmiMemoryAtomicIncrementMemOrder(someInt, MemModel) CmiMemoryAtomicIncrementSimple(someInt);
2060 #define CmiMemoryAtomicDecrementMemOrder(someInt, MemModel) CmiMemoryAtomicDecrementSimple(someInt);
2061 #define CmiMemoryAtomicFetchAndIncMemOrder(input,output, MemModel) CmiMemoryAtomicFetchAndIncSimple(input, output);
2062 #if CMK_GCC_X86_ASM /*SYNC_PRIM*/
2063 #if 1
2064 #define CmiMemoryAtomicIncrementSimple(someInt)  __asm__ __volatile__("lock incl (%0)" :: "r" (&(someInt)))
2065 #define CmiMemoryAtomicDecrementSimple(someInt)  __asm__ __volatile__("lock decl (%0)" :: "r" (&(someInt)))
2066 #else /* 1 */
2067 /* this might be slightly faster, but does not compile with -O3 on netlrts-darwin-x86_64 */
2068 #define CmiMemoryAtomicIncrement(someInt)  __asm__ __volatile__("lock incl %0" :: "m" (someInt))
2069 #define CmiMemoryAtomicDecrement(someInt)  __asm__ __volatile__("lock decl %0" :: "m" (someInt))
2070 #endif /* 1 */
2071 #define CmiMemoryAtomicFetchAndIncSimple(input,output) __asm__ __volatile__( \
2072         "movl $1, %1\n\t" \
2073         "lock xaddl %1, %0" \
2074         : "=m"(input), "=r"(output) : "m"(input) : "memory")
2075 #else
2076 #define CMK_NO_ASM_AVAILABLE    1
2077 extern CmiNodeLock cmiMemoryLock;
2078 #define CmiMemoryAtomicIncrementSimple(someInt)  { CmiLock(cmiMemoryLock); someInt=someInt+1; CmiUnlock(cmiMemoryLock); }
2079 #define CmiMemoryAtomicDecrementSimple(someInt)  { CmiLock(cmiMemoryLock); someInt=someInt-1; CmiUnlock(cmiMemoryLock); }
2080 #define CmiMemoryAtomicFetchAndIncSimple(input,output) { CmiLock(cmiMemoryLock); output=input; input=output+1; CmiUnlock(cmiMemoryLock); }
2081 #endif
2082 #endif /* CMK_C_SYNC_ADD_AND_FETCH_PRIMITIVE */
2083
2084 #if CMK_C_SYNC_SYNCHRONIZE_PRIMITIVE
2085 #define CmiMemoryReadFence()                 __sync_synchronize()
2086 #define CmiMemoryWriteFence()                __sync_synchronize()
2087 #else
2088 #define CMK_NO_ASM_AVAILABLE    1
2089 extern CmiNodeLock cmiMemoryLock;
2090 #define CmiMemoryReadFence()               { CmiLock(cmiMemoryLock); CmiUnlock(cmiMemoryLock); }
2091 #define CmiMemoryWriteFence()              { CmiLock(cmiMemoryLock); CmiUnlock(cmiMemoryLock); }
2092 #endif /* CMK_C_SYNC_SYNCHRONIZE_PRIMITIVE */
2093
2094 #else  /* for non-SMP, no need to define */
2095 #define CmiMemoryReadFence()
2096 #define CmiMemoryWriteFence()
2097 #define CmiMemoryAtomicIncrement(someInt)  someInt=someInt+1
2098 #define CmiMemoryAtomicDecrement(someInt)  someInt=someInt-1
2099 #define CmiMemoryAtomicFetchAndInc(input,output) output=input; input=output+1;
2100 #endif /*if CMK_SMP*/
2101
2102 /******** Performance Counters ********/
2103 void CmiInitCounters();
2104 void CmiStartCounters(int events[], int numEvents);
2105 void CmiStopCounters(int events[], CMK_TYPEDEF_INT8 values[], int numEvents);
2106
2107 /******** Trace ********/
2108
2109 /* this is the type for thread ID, mainly used for projection. */
2110 #define OBJ_ID_SZ 4
2111 typedef struct _CmiObjId {
2112 int id[OBJ_ID_SZ];
2113   /* 
2114    * **CWL** Note: setting initial values to -1 does not seem to be done for 
2115    *               LDObjid. Potential consistency problems could arise. This
2116    *               will probably have to be dealt with later.
2117    */
2118 #ifdef __cplusplus
2119   _CmiObjId() { 
2120     for (int i=0; i<OBJ_ID_SZ; i++) {
2121       id[i] = -1;
2122     }
2123   }
2124   bool isNull() {
2125     for (int i=0; i<OBJ_ID_SZ; i++) {
2126       if (id[i] != -1) return false;
2127     }
2128     return true;
2129   }
2130   bool operator==(const struct _CmiObjId& objid) const {
2131     for (int i=0; i<OBJ_ID_SZ; i++) if (id[i] != objid.id[i]) return false;
2132     return true;
2133   }
2134 #endif
2135 } CmiObjId;
2136
2137 /* public interface for thread id acquisition */
2138 CmiObjId *CthGetThreadID(CthThread th);
2139 void CthSetThreadID(CthThread th, int a, int b, int c);
2140
2141 void CthTraceResume(CthThread t);
2142
2143 #if CMK_FAULT_EVAC
2144 #if CMK_BIGSIM_CHARM
2145 #define CmiNodeAlive(x) (1)
2146 #else
2147 CpvExtern(char *,_validProcessors);
2148 #define CmiNodeAlive(x)  (CpvAccess(_validProcessors)[x])
2149 #endif
2150 #endif
2151
2152 int CmiEndianness(void);
2153
2154 #if CMK_CHARMDEBUG
2155 extern void setMemoryTypeChare(void*); /* for memory debugging */
2156 extern void setMemoryTypeMessage(void*); /* for memory debugging */
2157 #else
2158 #define setMemoryTypeChare(p) /* empty memory debugging method */
2159 #define setMemoryTypeMessage(p) /* empty memory debugging method */
2160 #endif
2161
2162 #include "conv-cpm.h"
2163 #include "conv-cpath.h"
2164 #include "conv-qd.h"
2165 #include "conv-random.h"
2166 #include "conv-lists.h"
2167 #include "conv-trace.h"
2168 #include "persistent.h"
2169 #if CMK_CELL
2170 #include "cell-api.h"
2171 #endif
2172
2173 #include "conv-rdma.h"
2174
2175 /* The flag tells whether we are in the process of doing out-of-core emulation in BigSim */
2176 extern int _BgOutOfCoreFlag;
2177 extern int _BgInOutOfCoreMode;
2178
2179 #ifdef ADAPT_SCHED_MEM
2180 extern int numMemCriticalEntries;
2181 extern int *memCriticalEntries;
2182 #endif
2183
2184 double CmiReadSize(const char *str);
2185
2186 #if  CMK_CONVERSE_UGNI
2187 void CmiTurnOnStats();
2188 void CmiTurnOffStats();
2189 #else
2190 #define CmiTurnOnStats()
2191 #define CmiTurnOffStats()
2192 #endif
2193
2194 /* CharmLibInterOperate should be a global variable as it will be
2195  * set only once by MPI ranks respectively.
2196  */
2197 extern int CharmLibInterOperate;
2198 CpvExtern(int,charmLibExitFlag);
2199
2200 /******** I/O wrappers ***********/
2201
2202 size_t CmiFwrite(const void *ptr, size_t size, size_t nmemb, FILE *f);
2203 CmiInt8 CmiPwrite(int fd, const char *buf, size_t bytes, size_t offset);
2204 int CmiOpen(const char *pathname, int flags, int mode);
2205 FILE *CmiFopen(const char *path, const char *mode);
2206 int CmiFclose(FILE *fp);
2207
2208 #if CMK_HAS_LOG2
2209 #define CmiLog2   log2
2210 #define CmiILog2  log2
2211 #else
2212 extern unsigned int CmiILog2(unsigned int);
2213 extern double CmiLog2(double);
2214 #endif
2215
2216 #if defined(__cplusplus)
2217 }                                         /* end of extern "C"  */
2218 #endif
2219
2220 #if CMK_GRID_QUEUE_AVAILABLE
2221 #if defined(__cplusplus)
2222 extern "C" int CmiGetCluster (int pe);
2223 extern "C" int CmiGridQueueGetInterval ();
2224 extern "C" int CmiGridQueueGetThreshold ();
2225 extern "C" void CmiGridQueueRegister (int gid, int nInts, int index1, int index2, int index3);
2226 extern "C" void CmiGridQueueDeregister (int gid, int nInts, int index1, int index2, int index3);
2227 extern "C" void CmiGridQueueDeregisterAll ();
2228 extern "C" int CmiGridQueueLookup (int gid, int nInts, int index1, int index2, int index3);
2229 extern "C" int CmiGridQueueLookupMsg (char *msg);
2230 #else
2231 extern int CmiGetCluster (int pe);
2232 extern int CmiGridQueueGetInterval ();
2233 extern int CmiGridQueueGetThreshold ();
2234 extern void CmiGridQueueRegister (int gid, int nInts, int index1, int index2, int index3);
2235 extern void CmiGridQueueDeregister (int gid, int nInts, int index1, int index2, int index3);
2236 extern void CmiGridQueueDeregisterAll ();
2237 extern int CmiGridQueueLookup (int gid, int nInts, int index1, int index2, int index3);
2238 extern int CmiGridQueueLookupMsg (char *msg);
2239 #endif
2240 #endif
2241
2242 #include "debug-conv.h"
2243
2244 typedef struct {
2245   CmiUInt4 msgSize;
2246   CmiUInt2 senderPe;
2247   CmiUInt2 destination;
2248 } CmiFragmentHeader;
2249
2250 #if CMK_SMP && CMK_LEVERAGE_COMMTHREAD
2251 #if defined(__cplusplus)
2252 #define EXTERN extern "C"
2253 #else
2254 #define EXTERN extern
2255 #endif
2256 typedef void (*CmiCommThdFnPtr)(int numParams, void *params);
2257 typedef struct CmiNotifyCommThdMsg {
2258     char core[CmiMsgHeaderSizeBytes];
2259     CmiCommThdFnPtr fn;
2260     int numParams;
2261     void *params;
2262     int toKeep; /* whether to free this msg by comm thread when the msg is processed */ 
2263 }CmiNotifyCommThdMsg;
2264
2265 EXTERN CmiNotifyCommThdMsg *CmiCreateNotifyCommThdMsg(CmiCommThdFnPtr fn, int numParams, void *params, int toKeep);
2266 EXTERN void CmiFreeNotifyCommThdMsg(CmiNotifyCommThdMsg *msg);
2267 /* Initialize a notification msg */
2268 EXTERN void CmiResetNotifyCommThdMsg(CmiNotifyCommThdMsg *msg, CmiCommThdFnPtr fn, int numParams, void *params, int toKeep);
2269 /* Enqueue the msg into the local comm thread, and wait for being processed */
2270 EXTERN void CmiNotifyCommThd(CmiNotifyCommThdMsg *msg);
2271 #endif
2272
2273 CpvExtern(int, _urgentSend);
2274 #if CMK_USE_OOB
2275 #define CmiEnableUrgentSend(yn)   CpvAccess(_urgentSend)=(yn)
2276 #else
2277 #define CmiEnableUrgentSend(yn)   
2278 #endif
2279
2280 #if CMK_SMP && CMK_TASKQUEUE
2281 #include "taskqueue.h" /* for tasks queue */
2282 #include "conv-taskQ.h" /* for standalone-OpenMP */
2283 #define CsdTaskEnqueue(x) TaskQueuePush((TaskQueue)CpvAccess(CsdTaskQueue),x)
2284 #define CsdTaskPop() TaskQueuePop((TaskQueue)CpvAccess(CsdTaskQueue))
2285 #if CMK_OMP
2286 #if defined(__cplusplus)
2287 extern "C" int CmiGetCurKnownOmpThreads();
2288 #else
2289 extern int CmiGetCurKnownOmpThreads();
2290 #endif
2291 #endif
2292 #endif
2293 CpvCExtern(int, isHelperOn);
2294 #if defined(__cplusplus)
2295 extern "C" void CmiSetPeHelpsOtherThreads(int);
2296 #else
2297 extern void CmiSetPeHelpsOtherThreads(int);
2298 #endif
2299 #endif /* CONVERSE_H */
2300
2301