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