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