modified the interface, added a new possibility of Cmi VectorSends to pack inside
[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 /**
37   Grab configuration files generated by build and configure scripts. 
38 */
39 #include "conv-config.h"
40
41 #if CMK_HAS_STDINT_H
42 #include <stdint.h>
43 #endif
44
45 #include <stdlib.h>
46
47 /* Paste the tokens x and y together, without any space between them.
48    The ANSI C way to do this is the bizarre ## "token-pasting" 
49    preprocessor operator.
50  */
51 #define CMK_CONCAT(x,y) x##y
52 /* Tag variable y as being from unit x: */
53 #define CMK_TAG(x,y) x##y##_
54
55
56 #include "pup_c.h"
57
58 /* the following flags denote properties of the C compiler,  */
59 /* not the C++ compiler.  If this is C++, ignore them.       */
60 #ifdef __cplusplus
61
62 /* Only C++ needs this backup bool defined.  We'll assume that C doesn't
63    use it */
64
65 #if ! CMK_BOOL_DEFINED
66 enum CmiBool {CmiFalse=0, CmiTrue=1};
67 #else
68 typedef bool CmiBool;
69 #define CmiFalse false
70 #define CmiTrue true
71 #endif
72
73 extern "C" {
74 #endif
75
76 /******************************************************************************
77  *
78  * Deal with Shared Memory
79  *
80  * Shared memory strongly affects how CPV, CSV, and CmiMyPe are defined,
81  * and how memory locking is performed. Therefore, we control all these
82  * functions with a single flag.
83  *
84  *****************************************************************************/
85
86 #ifdef __cplusplus
87 /* In C++, use new so t's constructor gets called */
88 # define CpvInit_Alloc(t,n) new t[n]
89 #else
90 # define CpvInit_Alloc(t,n) (t *)calloc(n,sizeof(t))
91 #endif
92
93 #if CMK_SHARED_VARS_UNAVAILABLE /* Non-SMP version of shared vars. */
94 extern int _Cmi_mype;
95 extern int _Cmi_numpes;
96 extern int _Cmi_myrank; /* Normally zero; only 1 during SIGIO handling */
97
98 #define CmiMyPe()           _Cmi_mype
99 #define CmiMyRank()         0
100 #define CmiNumPes()         _Cmi_numpes
101 #define CmiMyNodeSize()     1
102 #define CmiMyNode()         _Cmi_mype
103 #define CmiNumNodes()       _Cmi_numpes
104 #define CmiNodeFirst(node)  (node)
105 #define CmiNodeSize(node)   1
106 #define CmiNodeOf(pe)       (pe)
107 #define CmiRankOf(pe)       0
108
109 #define CpvDeclare(t,v) t CMK_TAG(Cpv_,v)[2]
110 #define CpvExtern(t,v)  extern t CMK_TAG(Cpv_,v)[2]
111 #define CpvCExtern(t,v)    CpvExtern(t,v)
112 #define CpvStaticDeclare(t,v) static t CMK_TAG(Cpv_,v)[2]
113 #define CpvInitialize(t,v) do {} while(0)
114 #define CpvInitialized(v) 1
115 #define CpvAccess(v) CMK_TAG(Cpv_,v)[_Cmi_myrank]
116 #define CpvAccessOther(v, r) CMK_TAG(Cpv_,v)[r]
117
118 extern void CmiMemLock();
119 extern void CmiMemUnlock();
120 #define CmiNodeBarrier() /*empty*/
121 #define CmiNodeAllBarrier() /*empty*/
122 #define CmiSvAlloc CmiAlloc
123
124 typedef int CmiNodeLock;
125 #define CmiCreateLock() (0)
126 #define CmiLock(lock) {(lock)++;}
127 #define CmiUnlock(lock)  {(lock)--;}
128 #define CmiTryLock(lock)  ((lock)?1:((lock)=1,0))
129 #define CmiDestroyLock(lock) /*empty*/
130
131 #endif
132
133 #if CMK_SHARED_VARS_POSIX_THREADS_SMP /*Used by the net-*-smp versions*/
134
135 #include <pthread.h>
136 #include <sched.h>
137 #ifdef CMK_FAKE_SCHED_YIELD
138 #include <unistd.h>
139 #define sched_yield() sleep(0)
140 #endif
141
142 extern int _Cmi_numpes;
143 extern int _Cmi_mynodesize;
144 extern int _Cmi_mynode;
145 extern int _Cmi_numnodes;
146
147 extern int CmiMyPe();
148 extern int CmiMyRank();
149 #define CmiNumPes()         _Cmi_numpes
150 #define CmiMyNodeSize()     _Cmi_mynodesize
151 #define CmiMyNode()         _Cmi_mynode
152 #define CmiNumNodes()       _Cmi_numnodes
153 extern int CmiNodeFirst(int node);
154 extern int CmiNodeSize(int node);
155 extern int CmiNodeOf(int pe);
156 extern int CmiRankOf(int pe);
157
158 #define CMK_CPV_IS_SMP sched_yield();
159
160 extern void CmiNodeBarrier(void);
161 extern void CmiNodeAllBarrier(void);
162 #define CmiSvAlloc CmiAlloc
163
164 typedef pthread_mutex_t *CmiNodeLock;
165 extern CmiNodeLock CmiCreateLock();
166 #define CmiLock(lock) (pthread_mutex_lock(lock))
167 #define CmiUnlock(lock) (pthread_mutex_unlock(lock))
168 #define CmiTryLock(lock) (pthread_mutex_trylock(lock))
169 extern void CmiDestroyLock(CmiNodeLock lock);
170
171 extern CmiNodeLock CmiMemLock_lock;
172 #define CmiMemLock() do{if (CmiMemLock_lock) CmiLock(CmiMemLock_lock);} while (0)
173 #define CmiMemUnlock() do{if (CmiMemLock_lock) CmiUnlock(CmiMemLock_lock);} while (0)
174
175 #endif
176
177
178 #if CMK_SHARED_VARS_EXEMPLAR /* Used only by HP Exemplar version */
179
180 #include <spp_prog_model.h>
181 #include <cps.h>
182
183 extern int _Cmi_numpes;
184 extern int _Cmi_mynodesize;
185
186 #define CmiMyPe()           (my_thread())
187 #define CmiMyRank()         (my_thread())
188 #define CmiNumPes()         _Cmi_numpes
189 #define CmiMyNodeSize()     _Cmi_numpes
190 #define CmiMyNode()         0
191 #define CmiNumNodes()       1
192 #define CmiNodeFirst(node)  0
193 #define CmiNodeSize(node)   _Cmi_numpes
194 #define CmiNodeOf(pe)       0
195 #define CmiRankOf(pe)       (pe)
196
197 #define CMK_CPV_IS_SMP {} 
198
199 extern void CmiMemLock();
200 extern void CmiMemUnlock();
201 extern void CmiNodeBarrier(void);
202 extern void *CmiSvAlloc(int);
203
204 typedef cps_mutex_t *CmiNodeLock;
205 extern CmiNodeLock CmiCreateLock(void);
206 #define CmiLock(lock) (cps_mutex_lock(lock))
207 #define CmiUnlock(lock) (cps_mutex_unlock(lock))
208 #define CmiTryLock(lock) (cps_mutex_trylock(lock))
209 #define CmiDestroyLock(lock) (cps_mutex_free(lock))
210
211 #endif
212
213 #if CMK_SHARED_VARS_UNIPROCESSOR /*Used only by uth- and sim- versions*/
214
215 extern int _Cmi_mype;
216 extern int _Cmi_numpes;
217
218 #define CmiMyPe()              _Cmi_mype
219 #define CmiMyRank()            _Cmi_mype
220 #define CmiNumPes()            _Cmi_numpes
221 #define CmiMyNodeSize()        _Cmi_numpes
222 #define CmiMyNode()            0
223 #define CmiNumNodes()          1
224 #define CmiNodeFirst(node)     0
225 #define CmiNodeSize(node)      _Cmi_numpes
226 #define CmiNodeOf(pe)          0
227 #define CmiRankOf(pe)          (pe)
228
229 #define CpvDeclare(t,v) t* CMK_TAG(Cpv_,v)
230 #define CpvExtern(t,v)  extern t* CMK_TAG(Cpv_,v)
231 #define CpvCExtern(t,v)  extern "C" t* CMK_TAG(Cpv_,v)
232 #define CpvStaticDeclare(t,v) static t* CMK_TAG(Cpv_,v)
233 #define CpvInitialize(t,v)\
234   do  { if (CMK_TAG(Cpv_,v)==0)\
235         { CMK_TAG(Cpv_,v) = CpvInit_Alloc(t,CmiNumPes()); }}\
236   while(0)
237 #define CpvInitialized(v) (0!=CMK_TAG(Cpv_,v))
238 #define CpvAccess(v) CMK_TAG(Cpv_,v)[CmiMyPe()]
239 #define CpvAccessOther(v, r) CMK_TAG(Cpv_,v)[r]
240
241 #define CmiMemLock() 0
242 #define CmiMemUnlock() 0
243 extern void CmiNodeBarrier();
244 extern void CmiNodeAllBarrier();
245 #define CmiSvAlloc CmiAlloc
246
247 typedef int *CmiNodeLock;
248 extern CmiNodeLock  CmiCreateLock(void);
249 extern void         CmiLock(CmiNodeLock lock);
250 extern void         CmiUnlock(CmiNodeLock lock);
251 extern int          CmiTryLock(CmiNodeLock lock);
252 extern void         CmiDestroyLock(CmiNodeLock lock);
253
254 #endif
255
256 #if CMK_SHARED_VARS_PTHREADS /*Used only by origin-pthreads*/
257
258 #include <pthread.h>
259 #include <sched.h>
260
261 extern int CmiMyPe();
262 extern int _Cmi_numpes;
263
264 #define CmiNumPes()            _Cmi_numpes
265 #define CmiMyRank()            CmiMyPe()
266 #define CmiMyNodeSize()        _Cmi_numpes
267 #define CmiMyNode()            0
268 #define CmiNumNodes()          1
269 #define CmiNodeFirst(node)     0
270 #define CmiNodeSize(node)      _Cmi_numpes
271 #define CmiNodeOf(pe)          0
272 #define CmiRankOf(pe)          (pe)
273
274 #define CMK_CPV_IS_SMP sched_yield();
275
276 extern void CmiMemLock();
277 extern void CmiMemUnlock();
278 extern void CmiNodeBarrier();
279 extern void CmiNodeAllBarrier();
280 #define CmiSvAlloc CmiAlloc
281
282 typedef pthread_mutex_t *CmiNodeLock;
283 extern CmiNodeLock  CmiCreateLock(void);
284 extern void         CmiLock(CmiNodeLock lock);
285 extern void         CmiUnlock(CmiNodeLock lock);
286 extern int          CmiTryLock(CmiNodeLock lock);
287 extern void         CmiDestroyLock(CmiNodeLock lock);
288
289 #endif
290
291 #if CMK_SHARED_VARS_NT_THREADS /*Used only by win32 versions*/
292
293 #include <windows.h>
294
295 extern int _Cmi_numpes;
296 extern int _Cmi_mynodesize;
297 extern int _Cmi_mynode;
298 extern int _Cmi_numnodes;
299
300 extern int CmiMyPe();
301 extern int CmiMyRank();
302 #define CmiNumPes()         _Cmi_numpes
303 #define CmiMyNodeSize()     _Cmi_mynodesize
304 #define CmiMyNode()         _Cmi_mynode
305 #define CmiNumNodes()       _Cmi_numnodes
306 extern int CmiNodeFirst(int node);
307 extern int CmiNodeSize(int node);
308 extern int CmiNodeOf(int pe);
309 extern int CmiRankOf(int pe);
310
311 #define CMK_CPV_IS_SMP Sleep(0);
312
313 extern void CmiNodeBarrier(void);
314 extern void CmiNodeAllBarrier(void);
315 #define CmiSvAlloc CmiAlloc
316
317 typedef HANDLE CmiNodeLock;
318 extern  CmiNodeLock CmiCreateLock(void);
319 #define CmiLock(lock) (WaitForSingleObject(lock, INFINITE))
320 #define CmiUnlock(lock) (ReleaseMutex(lock))
321 #define CmiTryLock(lock) (WaitForSingleObject(lock, 0))
322 extern  void CmiDestroyLock(CmiNodeLock lock);
323
324 extern CmiNodeLock CmiMemLock_lock;
325 #define CmiMemLock() do{if (CmiMemLock_lock) CmiLock(CmiMemLock_lock);} while (0)
326 #define CmiMemUnlock() do{if (CmiMemLock_lock) CmiUnlock(CmiMemLock_lock);} while (0)
327
328 #endif
329
330 #if CMK_SHARED_VARS_UNAVAILABLE   /* non-SMP version */
331
332 typedef int CmiImmediateLockType;
333 extern int _immediateLock;
334 extern int _immediateFlag;
335 #define CmiCreateImmediateLock() (0)
336 #define CmiImmediateLock(ignored) { _immediateLock++; }
337 #if CMK_IMMEDIATE_MSG
338 #define CmiImmediateUnlock(ignored) \
339   { _immediateLock--; \
340     if(_immediateFlag) \
341       CmiProbeImmediateMsg(); } 
342 #else
343 #define CmiImmediateUnlock(ignored) { _immediateLock--; }
344 #endif
345 #define CmiCheckImmediateLock(ignored) \
346   ((_immediateLock)?((_immediateFlag=1),1):0)
347 #define CmiClearImmediateFlag() { _immediateFlag=0; }
348
349 #else /* SMP and all other weird versions */
350
351 typedef CmiNodeLock CmiImmediateLockType;
352 #define CmiCreateImmediateLock() CmiCreateLock()
353 #define CmiImmediateLock(immediateLock) CmiLock((immediateLock))
354 #define CmiImmediateUnlock(immediateLock) CmiUnlock((immediateLock)) 
355 #define CmiCheckImmediateLock(ignored)  (0)
356 #define CmiClearImmediateFlag() 
357
358 #endif
359
360 /* This is the default Cpv implmentation for SMP-style systems:
361 A Cpv variable is actually a pointer to an array of values, one
362 for each processor in the node.
363 */
364 #ifdef CMK_CPV_IS_SMP
365
366 #define CpvDeclare(t,v) t* CMK_TAG(Cpv_,v)
367 #define CpvExtern(t,v)  extern t* CMK_TAG(Cpv_,v)
368 #define CpvCExtern(t,v)  extern "C" t* CMK_TAG(Cpv_,v)
369 #define CpvStaticDeclare(t,v) static t* CMK_TAG(Cpv_,v)
370 #define CpvInitialize(t,v)\
371     do { \
372        if (CmiMyRank()) { \
373                 while (!CpvInitialized(v)) CMK_CPV_IS_SMP \
374        } else { \
375                CMK_TAG(Cpv_,v)=CpvInit_Alloc(t,1+CmiMyNodeSize());\
376        } \
377     } while(0)
378 #define CpvInitialized(v) (0!=CMK_TAG(Cpv_,v))
379 #define CpvAccess(v) CMK_TAG(Cpv_,v)[CmiMyRank()]
380 #define CpvAccessOther(v, r) CMK_TAG(Cpv_,v)[r]
381
382 #endif
383
384 /*Csv are the same almost everywhere:*/
385 #ifndef CsvDeclare
386 #define CsvDeclare(t,v) t CMK_TAG(Csv_,v)
387 #define CsvStaticDeclare(t,v) static t CMK_TAG(Csv_,v)
388 #define CsvExtern(t,v) extern t CMK_TAG(Csv_,v)
389 #define CsvInitialize(t,v) do{}while(0)
390 #define CsvAccess(v) CMK_TAG(Csv_,v)
391 #endif
392
393 extern void CmiBarrier(void);
394 extern void CmiBarrierZero(void);
395
396 /** Return 1 if our outgoing message queue 
397    for this node is longer than this many bytes. */
398 int CmiLongSendQueue(int forNode,int longerThanBytes);
399
400 /******** CMI: TYPE DEFINITIONS ********/
401
402 typedef CMK_TYPEDEF_INT2      CmiInt2;
403 typedef CMK_TYPEDEF_INT4      CmiInt4;
404 typedef CMK_TYPEDEF_INT8      CmiInt8;
405 typedef CMK_TYPEDEF_UINT2     CmiUInt2;
406 typedef CMK_TYPEDEF_UINT4     CmiUInt4;
407 typedef CMK_TYPEDEF_UINT8     CmiUInt8;
408 typedef CMK_TYPEDEF_FLOAT4    CmiFloat4;
409 typedef CMK_TYPEDEF_FLOAT8    CmiFloat8;
410
411 typedef void  *CmiCommHandle;
412 typedef void (*CmiHandler)(void *msg);
413 typedef void (*CmiHandlerEx)(void *msg,void *userPtr);
414
415 typedef struct CMK_MSG_HEADER_BASIC CmiMsgHeaderBasic;
416 typedef struct CMK_MSG_HEADER_EXT   CmiMsgHeaderExt;
417
418 #define CmiMsgHeaderSizeBytes (sizeof(CmiMsgHeaderBasic))
419 #define CmiExtHeaderSizeBytes (sizeof(CmiMsgHeaderExt))
420
421 /* all common extra fields in BigSim message header */
422 #define CMK_BLUEGENE_FIELDS  CmiInt4 nd,n; double rt; CmiInt2 tID, hID; char t, flag; CmiInt2 ref; CmiInt4 msgID, srcPe;
423
424 #ifndef CmiReservedHeaderSize
425 #if CMK_BLUEGENE_CHARM
426 #  define CmiReservedHeaderSize   CmiBlueGeneMsgHeaderSizeBytes
427 #else
428 #  define CmiReservedHeaderSize   CmiExtHeaderSizeBytes
429 #endif
430 #endif
431
432 /******** CMI, CSD: MANY LOW-LEVEL OPERATIONS ********/
433
434 typedef struct {
435         CmiHandlerEx hdlr;
436         void *userPtr;
437 } CmiHandlerInfo;
438
439 CpvExtern(CmiHandlerInfo*, CmiHandlerTable);
440 CpvExtern(int,         CmiHandlerMax);
441 CpvExtern(void*,       CsdSchedQueue);
442 #if CMK_OBJECT_QUEUE_AVAILABLE
443 CpvExtern(void*,       CsdObjQueue);
444 #endif
445 #if CMK_NODE_QUEUE_AVAILABLE
446 CsvExtern(void*,       CsdNodeQueue);
447 CsvExtern(CmiNodeLock, CsdNodeQueueLock);
448 #endif
449 CpvExtern(int,         CsdStopFlag);
450 CpvExtern(int,         CsdLocalCount);
451 #define CSD_LOCAL_MAX_DEFAULT 0
452
453 extern int CmiRegisterHandler(CmiHandler h);
454 extern int CmiRegisterHandlerEx(CmiHandlerEx h,void *userPtr);
455 #if CMI_LOCAL_GLOBAL_AVAILABLE
456 extern int CmiRegisterHandlerLocal(CmiHandler);
457 extern int CmiRegisterHandlerGlobal(CmiHandler);
458 #endif
459 extern void CmiNumberHandler(int n, CmiHandler h);
460 extern void CmiNumberHandlerEx(int n, CmiHandlerEx h,void *userPtr);
461
462 #define CmiGetHandler(m)  (((CmiMsgHeaderExt*)m)->hdl)
463 #define CmiGetXHandler(m) (((CmiMsgHeaderExt*)m)->xhdl)
464 #define CmiGetInfo(m)     (((CmiMsgHeaderExt*)m)->info)
465
466 #define CmiSetHandler(m,v)  do {((((CmiMsgHeaderExt*)m)->hdl)=(v));} while(0)
467 #define CmiSetXHandler(m,v) do {((((CmiMsgHeaderExt*)m)->xhdl)=(v));} while(0)
468 #define CmiSetInfo(m,v)     do {((((CmiMsgHeaderExt*)m)->info)=(v));} while(0)
469
470 #define CmiHandlerToInfo(n) (CpvAccess(CmiHandlerTable)[n])
471 #define CmiHandlerToFunction(n) (CmiHandlerToInfo(n).hdlr)
472 #define CmiGetHandlerInfo(env) (CmiHandlerToInfo(CmiGetHandler(env)))
473 #define CmiGetHandlerFunction(env) (CmiHandlerToFunction(CmiGetHandler(env)))
474
475 #if CMK_MEM_CHECKPOINT
476 extern int cur_restart_phase;      /* number of restarts */
477 #undef CmiSetHandler
478 #define CmiSetHandler(m,v)  do {(((CmiMsgHeaderExt*)m)->hdl)=(v); (((CmiMsgHeaderExt*)m)->pn)=cur_restart_phase;} while(0)
479 #endif
480
481 /** This header goes before each chunk of memory allocated with CmiAlloc. 
482     See the comment in convcore.c for details on the fields.
483 */
484 typedef struct {
485   int size;
486   int ref;
487 } CmiChunkHeader;
488
489 /* Given a user chunk m, extract the enclosing chunk header fields: */
490 #define SIZEFIELD(m) (((CmiChunkHeader *)(m))[-1].size)
491 #define REFFIELD(m) (((CmiChunkHeader *)(m))[-1].ref)
492 #define BLKSTART(m) (((CmiChunkHeader *)(m))-1)
493
494 void    *CmiAlloc(int size);
495 void     CmiReference(void *blk);
496 int      CmiSize(void *blk);
497 void     CmiFree(void *blk);
498
499 #ifndef CMI_TMP_SKIP
500 void *CmiTmpAlloc(int size);
501 void CmiTmpFree(void *);
502 #endif
503
504 /* Pool features */
505
506
507 /* Various special features of certain -memory modes: */
508 void CmiMemoryCheck(void); /* heap check, for -memory paranoid */
509 void CmiMemoryMark(void); /* ignore current allocations, for -memory leak */
510 void CmiMemoryMarkBlock(void *blk); /* ignore this allocation, for -memory leak */
511 void CmiMemorySweep(const char *where); /* print current allocations, for -memory leak */
512 int CmiMemoryUsage();
513
514 #define CMI_MEMORY_IS_ISOMALLOC (1<<1)
515 #define CMI_MEMORY_IS_PARANOID (1<<2)
516 int CmiMemoryIs(int flag); /* return state of this flag */
517
518 void CmiMkdir(const char *dirName);
519
520 double   CmiCpuTimer(void);
521
522 #if CMK_TIMER_USE_RDTSC 
523 #ifndef __x86_64__
524 # if ! (CMK_GCC_X86_ASM || CMK_GCC_IA64_ASM)
525 /* Can't use rdtsc unless we have x86 or ia64 assembly: */
526 #  undef CMK_TIMER_USE_RDTSC
527 #  undef CMK_TIMER_USE_GETRUSAGE
528 #  define CMK_TIMER_USE_RDTSC 0
529 #  define CMK_TIMER_USE_GETRUSAGE 1
530 # endif
531 #endif
532 #endif
533
534 #if CMK_TIMER_USE_RDTSC 
535 extern double _cpu_speed_factor;
536
537 static __inline__ unsigned long long int rdtsc(void)
538 {
539         unsigned long long int x;
540 #ifdef __x86_64__
541         /* taken from papi code ("perfctr-p3.c") for machines like opteron */
542         do {
543           unsigned int a,d;
544           asm volatile("rdtsc" : "=a" (a), "=d" (d));
545           (x) = ((unsigned long)a) | (((unsigned long)d)<<32);
546         } while(0);
547 #elif CMK_GCC_IA64_ASM
548         __asm__ __volatile__("mov %0=ar.itc" : "=r"(x) :: "memory");
549 #elif CMK_GCC_X86_ASM
550         __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
551 #else
552 #  error "Unknown assembly format-- can't use CMK_TIMER_USE_RDTSC."
553 #endif
554         return x;
555 }
556
557 #define CmiWallTimer() ((double)rdtsc()*(_cpu_speed_factor))
558 #define CmiTimer CmiCpuTimer
559 double   CmiStartTimer(void);
560 #define CmiTimerIsSynchronized()        (0)
561
562 #else
563 void     CmiTimerInit();
564 double   CmiTimer(void);
565 double   CmiWallTimer(void);
566 #define  CmiStartTimer()                (0.0)
567 int      CmiTimerIsSynchronized();
568 #endif
569
570 #if CMK_NODE_QUEUE_AVAILABLE
571
572 #define CsdNodeEnqueueGeneral(x,s,i,p) do { \
573           CmiLock(CsvAccess(CsdNodeQueueLock));\
574           CqsEnqueueGeneral(CsvAccess(CsdNodeQueue),(x),(s),(i),(p)); \
575           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
576         } while(0)
577 #define CsdNodeEnqueueFifo(x)     do { \
578           CmiLock(CsvAccess(CsdNodeQueueLock));\
579           CqsEnqueueFifo(CsvAccess(CsdNodeQueue),(x)); \
580           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
581         } while(0)
582 #define CsdNodeEnqueueLifo(x)     do { \
583           CmiLock(CsvAccess(CsdNodeQueueLock));\
584           CqsEnqueueLifo(CsvAccess(CsdNodeQueue),(x))); \
585           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
586         } while(0)
587 #define CsdNodeEnqueue(x)     do { \
588           CmiLock(CsvAccess(CsdNodeQueueLock));\
589           CqsEnqueueFifo(CsvAccess(CsdNodeQueue),(x));\
590           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
591         } while(0)
592
593 #define CsdNodeEmpty()            (CqsEmpty(CpvAccess(CsdNodeQueue)))
594 #define CsdNodeLength()           (CqsLength(CpvAccess(CsdNodeQueue)))
595
596 #else
597
598 #define CsdNodeEnqueueGeneral(x,s,i,p) (CsdEnqueueGeneral(x,s,i,p))
599 #define CsdNodeEnqueueFifo(x) (CqsEnqueueFifo(CpvAccess(CsdSchedQueue),(x)))
600 #define CsdNodeEnqueueLifo(x) (CqsEnqueueLifo(CpvAccess(CsdSchedQueue),(x)))
601 #define CsdNodeEnqueue(x)     (CsdEnqueue(x))
602 #define CsdNodeEmpty()        (CqsEmpty(CpvAccess(CsdSchedQueue)))
603 #define CsdNodeLength()       (CqsLength(CpvAccess(CsdSchedQueue)))
604
605 #endif
606
607 #define CsdEnqueueGeneral(x,s,i,p)\
608     (CqsEnqueueGeneral(CpvAccess(CsdSchedQueue),(x),(s),(i),(p)))
609 #define CsdEnqueueFifo(x)     (CqsEnqueueFifo(CpvAccess(CsdSchedQueue),(x)))
610 #define CsdEnqueueLifo(x)     (CqsEnqueueLifo(CpvAccess(CsdSchedQueue),(x)))
611 #define CsdEnqueue(x)         (CqsEnqueueFifo(CpvAccess(CsdSchedQueue),(x)))
612 #define CsdEmpty()            (CqsEmpty(CpvAccess(CsdSchedQueue)))
613 #define CsdLength()           (CqsLength(CpvAccess(CsdSchedQueue)))
614
615 #if CMK_CMIPRINTF_IS_A_BUILTIN /* these are implemented in machine.c */
616 void  CmiPrintf(const char *, ...);
617 void  CmiError(const char *, ...);
618 int   CmiScanf(const char *, ...);
619
620 #else /* standard definitions */
621
622 #include <stdio.h>
623
624 /*
625  * I made vprintf functions for CmiPrintf and CmiError, but on the
626  * O2K, there is no equivalent vscanf!
627
628  #define CmiPrintf printf
629  #define CmiError  printf
630 */
631 #include <stdarg.h>
632
633 void  CmiPrintf(const char *format, ...);
634 void  CmiError(const char *format, ...);
635 #define CmiScanf  scanf
636
637 #endif
638
639 #ifdef CMK_OPTIMIZE
640 #define CmiAssert(expr) ((void) 0)
641 #else
642 #if defined(__STDC__) || defined(__cplusplus)
643 #define __CMK_STRING(x) #x
644 #else
645 #define __CMK_STRING(x) "x"
646 #endif
647 extern void __cmi_assert(const char *, const char *, int);
648 #define CmiAssert(expr) \
649   ((void) ((expr) ? 0 :                   \
650      (__cmi_assert (__CMK_STRING(expr), __FILE__, __LINE__), 0)))
651 #endif
652
653 typedef void (*CmiStartFn)(int argc, char **argv);
654
655 /********* CSD - THE SCHEDULER ********/
656
657 CpvExtern(int, _ccd_numchecks);
658 extern void  CcdCallBacks();
659 #define CsdPeriodic() do{ if (CpvAccess(_ccd_numchecks)-- <= 0) CcdCallBacks(); } while(0)
660 #define CsdResetPeriodic()    CpvAccess(_ccd_numchecks) = 0;
661
662 extern void  CsdEndIdle(void);
663 extern void  CsdStillIdle(void);
664 extern void  CsdBeginIdle(void);
665
666 typedef struct {
667   void *localQ;
668   void *nodeQ;
669   void *schedQ;
670   int *localCounter;
671 #if CMK_OBJECT_QUEUE_AVAILABLE
672   void *objQ;
673 #endif
674   CmiNodeLock nodeLock;
675 } CsdSchedulerState_t;
676 extern void CsdSchedulerState_new(CsdSchedulerState_t *state);
677 extern void *CsdNextMessage(CsdSchedulerState_t *state);
678
679 extern void  *CmiGetNonLocal(void);
680 extern void   CmiNotifyIdle(void);
681
682 /*Different kinds of schedulers: generic, eternal, counting, polling*/
683 extern  int CsdScheduler(int maxmsgs);
684 extern void CsdScheduleForever(void);
685 extern  int CsdScheduleCount(int maxmsgs);
686 extern void CsdSchedulePoll(void);
687
688 #define CsdExitScheduler()  (CpvAccess(CsdStopFlag)++)
689
690 #if CMK_SPANTREE_USE_COMMON_CODE
691
692 #define CST_W  (CMK_SPANTREE_MAXSPAN)
693 #define CST_NN (CmiNumNodes())
694 #define CmiNodeSpanTreeParent(n) ((n)?(((n)-1)/CST_W):(-1))
695 #define CmiNodeSpanTreeChildren(n,c) do {\
696           int _i; \
697           for(_i=0; _i<CST_W; _i++) { \
698             int _x = (n)*CST_W+_i+1; \
699             if(_x<CST_NN) (c)[_i]=_x; \
700           }\
701         } while(0)
702 #define CmiNumNodeSpanTreeChildren(n) ((((n)+1)*CST_W<CST_NN)? CST_W : \
703           ((((n)*CST_W+1)>=CST_NN)?0:((CST_NN-1)-(n)*CST_W)))
704 #define CST_R(p) (CmiRankOf(p))
705 #define CST_NF(n) (CmiNodeFirst(n))
706 #define CST_SP(n) (CmiNodeSpanTreeParent(n))
707 #define CST_ND(p) (CmiNodeOf(p))
708 #define CST_NS(p) (CmiNodeSize(CST_ND(p)))
709 #define CmiSpanTreeParent(p) ((p)?(CST_R(p)?(CST_NF(CST_ND(p))+CST_R(p)/CST_W):CST_NF(CST_SP(CST_ND(p)))):(-1))
710 #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)))
711 #define CST_SC(p) (CmiNumNodeSpanTreeChildren(CST_ND(p)))
712 #define CmiNumSpanTreeChildren(p) (CST_R(p)?CST_C(p):(CST_SC(p)+CST_C(p)))
713 #define CmiSpanTreeChildren(p,c) do {\
714           int _i,_c=0; \
715           if(CST_R(p)==0) { \
716             for(_i=0;_i<CST_W;_i++) { \
717               int _x = CST_ND(p)*CST_W+_i+1; \
718               if(_x<CST_NN) (c)[_c++]=CST_NF(_x); \
719             }\
720           } \
721           for(_i=0;_i<CST_W;_i++) { \
722             int _x = CST_R(p)*CST_W+_i+1; \
723             if(_x<CST_NS(p)) (c)[_c++]=CST_NF(CST_ND(p))+_x; \
724           }\
725         } while(0)
726
727 #else
728
729 int      CmiNumSpanTreeChildren(int) ;
730 int      CmiSpanTreeParent(int) ;
731 void     CmiSpanTreeChildren(int node, int *children);
732 int      CmiNumNodeSpanTreeChildren(int);
733 int      CmiNodeSpanTreeParent(int) ;
734 void     CmiNodeSpanTreeChildren(int node, int *children) ;
735 #endif
736
737 /****** MULTICAST GROUPS ******/
738
739 typedef CMK_MULTICAST_GROUP_TYPE CmiGroup;
740
741 void     CmiGroupInit();
742 CmiGroup CmiEstablishGroup(int npes, int *pes);
743 void     CmiLookupGroup(CmiGroup grp, int *npes, int **pes);
744
745 /****** CMI MESSAGE TRANSMISSION ******/
746
747 void          CmiSyncSendFn(int, int, char *);
748 CmiCommHandle CmiAsyncSendFn(int, int, char *);
749 void          CmiFreeSendFn(int, int, char *);
750
751 void          CmiSyncBroadcastFn(int, char *);
752 CmiCommHandle CmiAsyncBroadcastFn(int, char *);
753 void          CmiFreeBroadcastFn(int, char *);
754
755 void          CmiSyncBroadcastAllFn(int, char *);
756 CmiCommHandle CmiAsyncBroadcastAllFn(int, char *);
757 void          CmiFreeBroadcastAllFn(int, char *);
758
759 void          CmiSyncListSendFn(int, int *, int, char*);
760 CmiCommHandle CmiAsyncListSendFn(int, int *, int, char*);
761 void          CmiFreeListSendFn(int, int *, int, char*);
762
763 void          CmiSyncMulticastFn(CmiGroup, int, char*);
764 CmiCommHandle CmiAsyncMulticastFn(CmiGroup, int, char*);
765 void          CmiFreeMulticastFn(CmiGroup, int, char*);
766
767 /* This first version has the default system parameter to 0 */
768 void          CmiSyncVectorSend(int, int, int *, char **);
769 CmiCommHandle CmiAsyncVectorSend(int, int, int *, char **);
770 void          CmiSyncVectorSendAndFree(int, int, int *, char **);
771
772 void          CmiSyncVectorSendSystem(int, int, int *, char **, int);
773 CmiCommHandle CmiAsyncVectorSendSystem(int, int, int *, char **, int);
774 void          CmiSyncVectorSendAndFreeSystem(int, int, int *, char **, int);
775
776 void          CmiMultipleSend(unsigned int, int, int *, char **);
777 void          CmiMultipleIsend(unsigned int, int, int *, char **);
778
779 int           CmiAsyncMsgSent(CmiCommHandle);
780 void          CmiReleaseCommHandle(CmiCommHandle);
781
782 #define CmiSyncSend(p,s,m)              (CmiSyncSendFn((p),(s),(char *)(m)))
783 #define CmiAsyncSend(p,s,m)             (CmiAsyncSendFn((p),(s),(char *)(m)))
784 #define CmiSyncSendAndFree(p,s,m)       (CmiFreeSendFn((p),(s),(char *)(m)))
785
786 #define CmiSyncBroadcast(s,m)           (CmiSyncBroadcastFn((s),(char *)(m)))
787 #define CmiAsyncBroadcast(s,m)          (CmiAsyncBroadcastFn((s),(char *)(m)))
788 #define CmiSyncBroadcastAndFree(s,m)    (CmiFreeBroadcastFn((s),(char *)(m)))
789
790 #define CmiSyncBroadcastAll(s,m)        (CmiSyncBroadcastAllFn((s),(char *)(m)))
791 #define CmiAsyncBroadcastAll(s,m)       (CmiAsyncBroadcastAllFn((s),(char *)(m)))
792 #define CmiSyncBroadcastAllAndFree(s,m) (CmiFreeBroadcastAllFn((s),(char *)(m)))
793
794 #define CmiSyncListSend(n,l,s,m)        (CmiSyncListSendFn((n),(l),(s),(char *)(m)))
795 #define CmiAsyncListSend(n,l,s,m)       (CmiAsyncListSendFn((n),(l),(s),(char *)(m)))
796 #define CmiSyncListSendAndFree(n,l,s,m) (CmiFreeListSendFn((n),(l),(s),(char *)(m)))
797
798 #define CmiSyncMulticast(g,s,m)         (CmiSyncMulticastFn((g),(s),(char*)(m)))
799 #define CmiAsyncMulticast(g,s,m)        (CmiAsyncMulticastFn((g),(s),(char*)(m)))
800 #define CmiSyncMulticastAndFree(g,s,m)  (CmiFreeMulticastFn((g),(s),(char*)(m)))
801
802 #if CMK_NODE_QUEUE_AVAILABLE
803 void          CmiSyncNodeSendFn(int, int, char *);
804 CmiCommHandle CmiAsyncNodeSendFn(int, int, char *);
805 void          CmiFreeNodeSendFn(int, int, char *);
806
807 void          CmiSyncNodeBroadcastFn(int, char *);
808 CmiCommHandle CmiAsyncNodeBroadcastFn(int, char *);
809 void          CmiFreeNodeBroadcastFn(int, char *);
810
811 void          CmiSyncNodeBroadcastAllFn(int, char *);
812 CmiCommHandle CmiAsyncNodeBroadcastAllFn(int, char *);
813 void          CmiFreeNodeBroadcastAllFn(int, char *);
814 #endif
815
816 #if CMK_NODE_QUEUE_AVAILABLE
817 #define CmiSyncNodeSend(p,s,m)          (CmiSyncNodeSendFn((p),(s),(char *)(m)))
818 #define CmiAsyncNodeSend(p,s,m)             (CmiAsyncNodeSendFn((p),(s),(char *)(m)))
819 #define CmiSyncNodeSendAndFree(p,s,m)       (CmiFreeNodeSendFn((p),(s),(char *)(m)))
820 #define CmiSyncNodeBroadcast(s,m)           (CmiSyncNodeBroadcastFn((s),(char *)(m)))
821 #define CmiAsyncNodeBroadcast(s,m)          (CmiAsyncNodeBroadcastFn((s),(char *)(m)))
822 #define CmiSyncNodeBroadcastAndFree(s,m)    (CmiFreeNodeBroadcastFn((s),(char *)(m)))
823 #define CmiSyncNodeBroadcastAll(s,m)        (CmiSyncNodeBroadcastAllFn((s),(char *)(m)))
824 #define CmiAsyncNodeBroadcastAll(s,m)       (CmiAsyncNodeBroadcastAllFn((s),(char *)(m)))
825 #define CmiSyncNodeBroadcastAllAndFree(s,m) (CmiFreeNodeBroadcastAllFn((s),(char *)(m)))
826 #else
827 #define CmiSyncNodeSend(n,s,m)        CmiSyncSend(CmiNodeFirst(n),s,m)
828 #define CmiAsyncNodeSend(n,s,m)       CmiAsyncSend(CmiNodeFirst(n),s,m)
829 #define CmiSyncNodeSendAndFree(n,s,m) CmiSyncSendAndFree(CmiNodeFirst(n),s,m)
830 #define CmiSyncNodeBroadcast(s,m)           do { \
831           int _i; \
832           for(_i=0; _i<CmiNumNodes(); _i++) \
833             if(_i != CmiMyNode()) \
834               CmiSyncSend(CmiNodeFirst(_i),s,m); \
835         } while(0)
836 #define CmiAsyncNodeBroadcast(s,m)          CmiSyncNodeBroadcast(s,m)
837 #define CmiSyncNodeBroadcastAndFree(s,m)    do { \
838           CmiSyncNodeBroadcast(s,m); \
839           CmiFree(m); \
840         } while(0)
841 #define CmiSyncNodeBroadcastAll(s,m)           do { \
842           int _i; \
843           for(_i=0; _i<CmiNumNodes(); _i++) \
844             CmiSyncSend(CmiNodeFirst(_i),s,m); \
845         } while(0)
846 #define CmiAsyncNodeBroadcastAll(s,m)       CmiSyncNodeBroadcastAll(s,m)
847 #define CmiSyncNodeBroadcastAllAndFree(s,m) do { \
848           CmiSyncNodeBroadcastAll(s,m); \
849           CmiFree(m); \
850         } while(0)
851 #endif
852
853 /******** CMI MESSAGE RECEPTION ********/
854
855 void   CmiDeliversInit();
856 int    CmiDeliverMsgs(int maxmsgs);
857 void   CmiDeliverSpecificMsg(int handler);
858 void   CmiHandleMessage(void *msg);
859
860 /******** CQS: THE QUEUEING SYSTEM ********/
861
862 #define CQS_QUEUEING_FIFO 2
863 #define CQS_QUEUEING_LIFO 3
864 #define CQS_QUEUEING_IFIFO 4
865 #define CQS_QUEUEING_ILIFO 5
866 #define CQS_QUEUEING_BFIFO 6
867 #define CQS_QUEUEING_BLIFO 7
868 #define CQS_QUEUEING_LFIFO 8
869 #define CQS_QUEUEING_LLIFO 9
870
871 /****** Isomalloc: Migratable Memory Allocation ********/
872 /*Simple block-by-block interface:*/
873 void *CmiIsomalloc(int sizeInBytes);
874 void  CmiIsomallocPup(pup_er p,void **block);
875 void  CmiIsomallocFree(void *block);
876
877 int   CmiIsomallocLength(void *block);
878 int   CmiIsomallocInRange(void *addr);
879
880 /*List-of-blocks interface:*/
881 struct CmiIsomallocBlockList {/*Circular doubly-linked list of blocks:*/
882         struct CmiIsomallocBlockList *prev,*next;
883         /*actual data of block follows here...*/
884 };
885 typedef struct CmiIsomallocBlockList CmiIsomallocBlockList;
886
887 /*Build/pup/destroy an entire blockList.*/
888 CmiIsomallocBlockList *CmiIsomallocBlockListNew(void);
889 void CmiIsomallocBlockListPup(pup_er p,CmiIsomallocBlockList **l);
890 void CmiIsomallocBlockListDelete(CmiIsomallocBlockList *l);
891
892 /*Allocate/free a block from this blockList*/
893 void *CmiIsomallocBlockListMalloc(CmiIsomallocBlockList *l,int nBytes);
894 void CmiIsomallocBlockListFree(void *doomedMallocedBlock);
895
896 /****** CTH: THE LOW-LEVEL THREADS PACKAGE ******/
897
898 typedef struct CthThreadStruct *CthThread;
899
900 typedef void        (*CthVoidFn)();
901 typedef void        (*CthAwkFn)(CthThread,int,
902                                 int prioBits,unsigned int *prioptr);
903 typedef CthThread   (*CthThFn)();
904
905 int        CthImplemented(void);
906
907 CthThread  CthPup(pup_er, CthThread);
908
909 CthThread  CthSelf(void);
910 CthThread  CthCreate(CthVoidFn, void *, int);
911 CthThread  CthCreateMigratable(CthVoidFn, void *, int);
912 void       CthResume(CthThread);
913 void       CthFree(CthThread);
914
915 void       CthSetSuspendable(CthThread, int);
916 int        CthIsSuspendable(CthThread);
917
918 void       CthSuspend(void);
919 void       CthAwaken(CthThread);
920 void       CthAwakenPrio(CthThread, int, int, unsigned int *);
921 void       CthSetStrategy(CthThread, CthAwkFn, CthThFn);
922 void       CthSetStrategyDefault(CthThread);
923 void       CthYield(void);
924 void       CthYieldPrio(int,int,unsigned int*);
925
926 void       CthSetNext(CthThread t, CthThread next);
927 CthThread  CthGetNext(CthThread t);
928
929 void       CthSwitchThread(CthThread t);
930
931 /* unimplemented: preemptive threads */
932 void       CthAutoYield(CthThread t, int flag);
933 double     CthAutoYieldFreq(CthThread t);
934 void       CthAutoYieldBlock(void);
935 void       CthAutoYieldUnblock(void);
936
937 /* Converse Thread Global (Ctg) global variable manipulation */
938 typedef struct CtgGlobalStruct *CtgGlobals;
939
940 /** Initialize the globals support (called on each processor). */
941 void CtgInit(void);
942
943 /** Copy the current globals into this new set */
944 CtgGlobals CtgCreate(void);
945 /** Install this set of globals. If g==NULL, returns to original globals. */
946 void CtgInstall(CtgGlobals g);
947 /** PUP this (not currently installed) globals set */
948 CtgGlobals CtgPup(pup_er, CtgGlobals g);
949 /** Delete this (not currently installed) set of globals. */
950 void CtgFree(CtgGlobals g);
951 /** Return the current global list */
952 CtgGlobals CtgCurrentGlobals(void);
953
954 /* The thread listener structure. The user must register one such listener
955         if he wants to find out when a thread is suspended or when it starts running
956         or gets destroyed. It can be used for tracing etc.
957 */
958
959 struct CthThreadListener;
960
961 typedef void (*CthThreadListener_suspend)(struct CthThreadListener *l);
962 typedef void (*CthThreadListener_resume)(struct CthThreadListener *l);
963 typedef void (*CthThreadListener_free)(struct CthThreadListener *l);
964
965 struct CthThreadListener {
966        /** This thread is about to block. */
967        CthThreadListener_suspend suspend;
968
969        /** This thread is about to begin execution after blocking. */
970        CthThreadListener_resume resume;
971
972        /** This thread is being destroyed.  */
973        CthThreadListener_free free;
974
975        /** Pointer to listener-specific data (if needed).
976            Set by listener.
977        */
978        void *data;
979
980        /** Pointer to the thread this listener controls.
981            Set by CthAddListener.
982         */
983        CthThread thread;
984
985        /** The next listener, or NULL at end of chain.
986            Set by CthAddListener, and used only by threads.c.
987        */
988        struct CthThreadListener *next;
989 };
990
991 /**
992   This listener is about to begin receiving suspend and
993 resume events for this thread.  "suspend", "resume", "free",
994 and "data" fields must all already be set.  When this thread
995 exits, l->free will be called on this listener, which should
996 deallocate the listener memory.
997 */
998 void CthAddListener(CthThread th,struct CthThreadListener *l);
999
1000 /**
1001   This is function is inserted into .def.h after thread creation.
1002   It serves as an interface for the user to add the listeners 
1003   as needed. User has to implement this somewhere in the system.
1004 */
1005 void CthUserAddListeners(CthThread th);
1006
1007
1008 /****** CTH: THREAD-PRIVATE VARIABLES ******/
1009
1010 #if CMK_THREADS_REQUIRE_NO_CPV
1011
1012 #define CthCpvDeclare(t,v)    t v
1013 #define CthCpvExtern(t,v)     extern t v
1014 #define CthCpvStatic(t,v)     static t v
1015 #define CthCpvInitialize(t,v) do {} while(0)
1016 #define CthCpvAccess(x)       x
1017
1018 #else
1019
1020 #define CthCpvDeclare(t,v)    CpvDeclare(t,v)
1021 #define CthCpvExtern(t,v)     CpvExtern(t,v)
1022 #define CthCpvStatic(t,v)     CpvStaticDeclare(t,v)
1023 #define CthCpvInitialize(t,v) CpvInitialize(t,v)
1024 #define CthCpvAccess(x)       CpvAccess(x)
1025
1026 #endif
1027
1028 CthCpvExtern(char *,CthData);
1029 extern int CthRegister(int dataSize);
1030 extern void CthRegistered(int dataOffMax);
1031 extern char *CthGetData(CthThread t);
1032
1033 #define CtvDeclare(t,v)         typedef t CtvType##v; CsvDeclare(int,CtvOffs##v)=(-1)
1034 #define CtvStaticDeclare(t,v)   typedef t CtvType##v; CsvStaticDeclare(int,CtvOffs##v)=(-1)
1035 #define CtvExtern(t,v)          typedef t CtvType##v; CsvExtern(int,CtvOffs##v)
1036 #define CtvAccess(v)            (*((CtvType##v *)(CthCpvAccess(CthData)+CsvAccess(CtvOffs##v))))
1037 #define CtvAccessOther(t,v)            (*((CtvType##v *)(CthGetData(t)+CsvAccess(CtvOffs##v))))
1038 #define CtvInitialize(t,v)      do { \
1039         if(CsvAccess(CtvOffs##v)==(-1)) \
1040                 CsvAccess(CtvOffs##v)=CthRegister(sizeof(CtvType##v));\
1041         else CthRegistered(CsvAccess(CtvOffs##v)+sizeof(CtvType##v));\
1042 } while(0)
1043
1044 /****** CFUTURE: CONVERSE FUTURES ******/
1045
1046 typedef struct Cfuture_s
1047 {
1048   int pe;
1049   struct Cfuture_data_s *data;
1050 }
1051 Cfuture;
1052
1053 #define CfutureValueData(v) ((void*)((v)->rest))
1054
1055 Cfuture       CfutureCreate(void);
1056 void          CfutureSet(Cfuture f, void *val, int len);
1057 void         *CfutureWait(Cfuture f);
1058 void          CfutureDestroy(Cfuture f);
1059
1060 void         *CfutureCreateBuffer(int bytes);
1061 void          CfutureDestroyBuffer(void *val);
1062 void          CfutureStoreBuffer(Cfuture f, void *value);
1063
1064 #define       CfuturePE(f) ((f).pe)
1065
1066 void CfutureInit();
1067
1068 /****** CLD: THE LOAD BALANCER ******/
1069
1070 #define CLD_ANYWHERE (-1)
1071 #define CLD_BROADCAST (-2)
1072 #define CLD_BROADCAST_ALL (-3)
1073
1074 typedef void (*CldPackFn)(void *msg);
1075
1076 typedef void (*CldInfoFn)(void *msg, 
1077                           CldPackFn *packer,
1078                           int *len,
1079                           int *queueing,
1080                           int *priobits, 
1081                           unsigned int **prioptr);
1082
1083 typedef int (*CldEstimator)(void);
1084
1085 int CldRegisterInfoFn(CldInfoFn fn);
1086 int CldRegisterPackFn(CldPackFn fn);
1087 void CldRegisterEstimator(CldEstimator fn);
1088 int CldEstimate(void);
1089 char *CldGetStrategy(void);
1090
1091 void CldEnqueue(int pe, void *msg, int infofn);
1092 void CldEnqueueMulti(int npes, int *pes, void *msg, int infofn);
1093 void CldNodeEnqueue(int node, void *msg, int infofn);
1094
1095 /****** CMM: THE MESSAGE MANAGER ******/
1096
1097 typedef struct CmmTableStruct *CmmTable;
1098
1099 #define CmmWildCard (-1)
1100
1101 typedef void (*CmmPupMessageFn)(pup_er p,void **msg);
1102 CmmTable CmmPup(pup_er p, CmmTable t, CmmPupMessageFn msgpup);
1103
1104 CmmTable   CmmNew();
1105 void       CmmFree(CmmTable t);
1106 void       CmmPut(CmmTable t, int ntags, int *tags, void *msg);
1107 void      *CmmFind(CmmTable t, int ntags, int *tags, int *returntags, int del);
1108 int        CmmEntries(CmmTable t);
1109 int        CmmGetLastTag(CmmTable t, int ntags, int *tags);
1110 #define    CmmGet(t,nt,tg,rt)   (CmmFind((t),(nt),(tg),(rt),1))
1111 #define    CmmProbe(t,nt,tg,rt) (CmmFind((t),(nt),(tg),(rt),0))
1112
1113 /******** ConverseInit and ConverseExit ********/
1114
1115 void ConverseInit(int, char**, CmiStartFn, int, int);
1116 void ConverseExit(void);
1117
1118 void CmiAbort(const char *);
1119 void CmiOutOfMemory(int nBytes);
1120
1121 #if CMK_MEMCHECK_OFF
1122 #define _MEMCHECK(p) do{}while(0)
1123 #else
1124 #define _MEMCHECK(p) do { \
1125                          if ((p)==0) CmiOutOfMemory(-1);\
1126                      } while(0)
1127 #endif
1128
1129 /******** CONVCONDS ********/
1130
1131 typedef void (*CcdVoidFn)(void *userParam,double curWallTime);
1132
1133 /*CPU conditions*/
1134 #define CcdPROCESSOR_BEGIN_BUSY 0
1135 #define CcdPROCESSOR_END_IDLE 0 /*Synonym*/
1136 #define CcdPROCESSOR_BEGIN_IDLE 1
1137 #define CcdPROCESSOR_END_BUSY 1 /*Synonym*/
1138 #define CcdPROCESSOR_STILL_IDLE 2
1139
1140 /*Periodic calls*/
1141 #define CcdPERIODIC       16 /*every few ms*/
1142 #define CcdPERIODIC_10ms  17 /*every 10ms (100Hz)*/
1143 #define CcdPERIODIC_100ms 18 /*every 100ms (10Hz)*/
1144 #define CcdPERIODIC_1second  19 /*every second*/
1145 #define CcdPERIODIC_1s       19 /*every second*/
1146 #define CcdPERIODIC_10second 20 /*every 10 seconds*/
1147 #define CcdPERIODIC_10seconds 20 /*every 10 seconds*/
1148 #define CcdPERIODIC_10s      20 /*every 10 seconds*/
1149 #define CcdPERIODIC_1minute  21 /*every minute*/
1150 #define CcdPERIODIC_10minute 22 /*every 10 minutes*/
1151 #define CcdPERIODIC_1hour    23 /*every hour*/
1152 #define CcdPERIODIC_12hour   24 /*every 12 hours*/
1153 #define CcdPERIODIC_1day     25 /*every day*/
1154
1155 /*Other conditions*/
1156 #define CcdQUIESCENCE 30
1157 #define CcdSIGUSR1 32+1
1158 #define CcdSIGUSR2 32+2
1159
1160 /*User-defined conditions start here*/
1161 #define CcdUSER    48
1162
1163 #define CcdIGNOREPE   -2
1164 #if CMK_CONDS_USE_SPECIAL_CODE
1165 typedef int (*CmiSwitchToPEFnPtr)(int pe);
1166 extern CmiSwitchToPEFnPtr CmiSwitchToPE;
1167 #else
1168 #define CmiSwitchToPE(pe)  pe
1169 #endif
1170 void CcdCallFnAfter(CcdVoidFn fnp, void *arg, double msecs);
1171 int CcdCallOnCondition(int condnum, CcdVoidFn fnp, void *arg);
1172 int CcdCallOnConditionKeep(int condnum, CcdVoidFn fnp, void *arg);
1173 void CcdCallFnAfterOnPE(CcdVoidFn fnp, void *arg, double msecs, int pe);
1174 int CcdCallOnConditionOnPE(int condnum, CcdVoidFn fnp, void *arg, int pe);
1175 int CcdCallOnConditionKeepOnPE(int condnum, CcdVoidFn fnp, void *arg, int pe);
1176 void CcdCancelCallOnCondition(int condnum, int idx);
1177 void CcdCancelCallOnConditionKeep(int condnum, int idx);
1178 void CcdRaiseCondition(int condnum);
1179
1180 /* Command-Line-Argument handling */
1181 void CmiArgGroup(const char *parentName,const char *groupName);
1182 int CmiGetArgInt(char **argv,const char *arg,int *optDest);
1183 int CmiGetArgIntDesc(char **argv,const char *arg,int *optDest,const char *desc);
1184 int CmiGetArgDouble(char **argv,const char *arg,double *optDest);
1185 int CmiGetArgDoubleDesc(char **argv,const char *arg,double *optDest,const char *desc);
1186 int CmiGetArgString(char **argv,const char *arg,char **optDest);
1187 int CmiGetArgStringDesc(char **argv,const char *arg,char **optDest,const char *desc);
1188 int CmiGetArgFlag(char **argv,const char *arg);
1189 int CmiGetArgFlagDesc(char **argv,const char *arg,const char *desc);
1190 void CmiDeleteArgs(char **argv,int k);
1191 int CmiGetArgc(char **argv);
1192 char **CmiCopyArgs(char **argv);
1193 int CmiArgGivingUsage(void);
1194
1195 /** 
1196    Extract the function-return pointers listed in the stack
1197    up to this depth.  nSkip is the number of enclosing functions
1198    to skip-- for example, nSkip==0 means the retPtrs[0]
1199    will be the caller of CmiBacktraceRecord.  
1200    Returns retPtrs[0..*nLevels-1] stack pointers.
1201    *nLevels may be decreased if not enough levels are available.
1202  */
1203 void CmiBacktraceRecord(void **retPtrs,int nSkip,int *nLevels);
1204
1205 /** Look up the names of these function pointers.
1206 Caller must free() the returned array, but not the individual
1207 strings.
1208 */
1209 char **CmiBacktraceLookup(void **srcPtrs,int nLevels);
1210
1211 /** Print out the names of these function pointers. */
1212 void CmiBacktracePrint(void **retPtrs,int nLevels);
1213
1214 /* Print (to stdout) the names of the functions that have been 
1215    called up to this point. nSkip is the number of routines on the
1216    top of the stack to *not* print out. */
1217 void CmiPrintStackTrace(int nSkip);
1218
1219 #if CMK_CMIDELIVERS_USE_COMMON_CODE
1220 CpvExtern(void*, CmiLocalQueue);
1221 #endif
1222
1223 char *CmiCopyMsg(char *msg, int len);
1224
1225 /******** Hypercube broadcast propagation (Binomial tree) ********/
1226
1227 /*
1228   This routing will receive a number k containing the dimension in the hypercube
1229   to be used for the broadcast, i.e. k=0 means sending only to MyPe^1, k=1 means
1230   sending to MyPe^2 and MyPe^1, etc.
1231   The array dest_pes will be filled with the id of the processors to which send,
1232   it has to be already allocated, the size should be at least k+1 to allow
1233   enough space.
1234   It return the number of processors to which send, i.e. the size of dest_pes.
1235   This may be less than k+1 due to not complete hypercubes.
1236   For example with pow(2,n)+2 procs and 0 broadcasting, proc pow(2,n) will
1237   receive from 0 in the first step but then it has only proc pow(2,n)+1 as
1238   destination, so most of the other dimentions will be skipped.
1239 */
1240 int HypercubeGetBcastDestinations(int mype, int total_pes, int k, int *dest_pes);
1241
1242 /******** Immediate Messages ********/
1243
1244 CpvExtern(int, CmiImmediateMsgHandlerIdx);
1245
1246
1247 CpvExtern(int, networkProgressCount);
1248 extern int networkProgressPeriod;
1249
1250 #if !CMK_MACHINE_PROGRESS_DEFINED
1251 #define CmiNetworkProgress() 
1252 #define CmiNetworkProgressAfter(p) 
1253
1254 void CmiProbeImmediateMsg();
1255
1256 #else
1257 void CmiMachineProgressImpl();
1258
1259 #define CmiProbeImmediateMsg CmiMachineProgressImpl
1260
1261 #define CmiNetworkProgress() {CpvAccess(networkProgressCount) ++; \
1262       if(CpvAccess(networkProgressCount) ==  networkProgressPeriod) { \
1263           CmiMachineProgressImpl(); \
1264           CpvAccess(networkProgressCount) = 0; \
1265       } \
1266 } \
1267
1268 #define CmiNetworkProgressAfter(p) {CpvAccess(networkProgressCount) ++; \
1269       if(CpvAccess(networkProgressCount) ==  p) { \
1270           CmiMachineProgressImpl(); \
1271           CpvAccess(networkProgressCount) = 0; \
1272       } \
1273 } \
1274
1275 #endif
1276
1277 /*
1278    to immediate-fy a Converse message, set the most significant bit to 1
1279    in the Converse handler (x|0x8000). 
1280 */
1281 #if CMK_IMMEDIATE_MSG
1282 void CmiDelayImmediate();
1283 #  define CmiBecomeImmediate(msg) do { \
1284         CmiSetHandler(msg, (CmiGetHandler(msg))|0x8000); \
1285      } while (0)
1286 #  define CmiIsImmediate(msg)      ((CmiGetHandler(msg)) & 0x8000) 
1287 #  define CmiImmediateHandler(msg) ((CmiGetHandler(msg)) ^ 0x8000)
1288 /*
1289 #  define CmiIsImmediate(msg)   ((CmiGetHandler(msg) == CpvAccessOther(CmiImmediateMsgHandlerIdx,0)))
1290 #  define CmiBecomeImmediate(msg) do {\
1291         CmiSetXHandler(msg,CmiGetHandler(msg)); \
1292         CmiSetHandler(msg,CpvAccessOther(CmiImmediateMsgHandlerIdx,0)); \
1293      } while (0)
1294 #  define CmiImemdiateHandler(msg) (CmiGetXHandler(msg))
1295 */
1296 /* 
1297   for non smp and non intr based version, it returns _immRunning
1298   for smp, this doesnot matter - CkMyPe() comparasion normaly fails and
1299            non threadsafe CqsEnqueueGeneral is avoided.
1300 */
1301 #if CMK_NET_VERSION && ! CMK_SMP
1302 extern int _immRunning;
1303 #  define CmiImmIsRunning()        (_immRunning)
1304 #else
1305 #  define CmiImmIsRunning()        (0)
1306 #endif
1307
1308 #else
1309 #  define CmiBecomeImmediate(msg) /* empty */
1310 #  define CmiIsImmediate(msg)   (0)
1311 #  define CmiImmIsRunning()       (0)
1312 #endif
1313
1314 /******** Performance Counters ********/
1315 void CmiInitCounters();
1316 void CmiStartCounters(int events[], int numEvents);
1317 void CmiStopCounters(int events[], CMK_TYPEDEF_INT8 values[], int numEvents);
1318
1319 /******** Trace ********/
1320
1321 /* this is the type for thread ID, mainly used for projection. */
1322 typedef struct {
1323 int id[3];
1324 } CmiObjId;
1325
1326 /* public interface for thread id acquisition */
1327 CmiObjId *CthGetThreadID(CthThread th);
1328 void CthSetThreadID(CthThread th, int a, int b, int c);
1329
1330 void CthTraceResume(CthThread t);
1331
1332 #include "conv-cpm.h"
1333 #include "conv-cpath.h"
1334 #include "conv-qd.h"
1335 #include "conv-random.h"
1336 #include "conv-lists.h"
1337 #include "conv-trace.h"
1338 #include "persistent.h"
1339
1340 #if defined(__cplusplus)
1341 }
1342 #endif
1343
1344 #include "debug-conv.h"
1345
1346
1347 #endif /* CONVERSE_H */