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