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