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