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