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