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