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