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