12698b9ef150e940f841f0c95967227df913648b
[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 void    *CmiAlloc(int size);
490 void     CmiReference(void *blk);
491 int      CmiSize(void *blk);
492 void     CmiFree(void *blk);
493
494 #ifndef CMI_TMP_SKIP
495 void *CmiTmpAlloc(int size);
496 void CmiTmpFree(void *);
497 #endif
498
499 /* Pool features */
500
501
502 /* Various special features of certain -memory modes: */
503 void CmiMemoryCheck(void); /* heap check, for -memory paranoid */
504 void CmiMemoryMark(void); /* ignore current allocations, for -memory leak */
505 void CmiMemoryMarkBlock(void *blk); /* ignore this allocation, for -memory leak */
506 void CmiMemorySweep(const char *where); /* print current allocations, for -memory leak */
507 int CmiMemoryUsage();
508
509 #define CMI_MEMORY_IS_ISOMALLOC (1<<1)
510 #define CMI_MEMORY_IS_PARANOID (1<<2)
511 int CmiMemoryIs(int flag); /* return state of this flag */
512
513 void CmiMkdir(const char *dirName);
514
515 double   CmiCpuTimer(void);
516
517 #if CMK_TIMER_USE_RDTSC 
518 #ifndef __x86_64__
519 # if ! (CMK_GCC_X86_ASM || CMK_GCC_IA64_ASM)
520 /* Can't use rdtsc unless we have x86 or ia64 assembly: */
521 #  undef CMK_TIMER_USE_RDTSC
522 #  undef CMK_TIMER_USE_GETRUSAGE
523 #  define CMK_TIMER_USE_RDTSC 0
524 #  define CMK_TIMER_USE_GETRUSAGE 1
525 # endif
526 #endif
527 #endif
528
529 #if CMK_TIMER_USE_RDTSC 
530 extern double _cpu_speed_factor;
531
532 static __inline__ unsigned long long int rdtsc(void)
533 {
534         unsigned long long int x;
535 #ifdef __x86_64__
536         /* taken from papi code ("perfctr-p3.c") for machines like opteron */
537         do {
538           unsigned int a,d;
539           asm volatile("rdtsc" : "=a" (a), "=d" (d));
540           (x) = ((unsigned long)a) | (((unsigned long)d)<<32);
541         } while(0);
542 #elif CMK_GCC_IA64_ASM
543         __asm__ __volatile__("mov %0=ar.itc" : "=r"(x) :: "memory");
544 #elif CMK_GCC_X86_ASM
545         __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
546 #else
547 #  error "Unknown assembly format-- can't use CMK_TIMER_USE_RDTSC."
548 #endif
549         return x;
550 }
551
552 #define CmiWallTimer() ((double)rdtsc()*(_cpu_speed_factor))
553 #define CmiTimer CmiCpuTimer
554 double   CmiStartTimer(void);
555 #define CmiTimerIsSynchronized()        (0)
556
557 #else
558 void     CmiTimerInit();
559 double   CmiTimer(void);
560 double   CmiWallTimer(void);
561 #define  CmiStartTimer()                (0.0)
562 int      CmiTimerIsSynchronized();
563 #endif
564
565 #if CMK_NODE_QUEUE_AVAILABLE
566
567 #define CsdNodeEnqueueGeneral(x,s,i,p) do { \
568           CmiLock(CsvAccess(CsdNodeQueueLock));\
569           CqsEnqueueGeneral(CsvAccess(CsdNodeQueue),(x),(s),(i),(p)); \
570           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
571         } while(0)
572 #define CsdNodeEnqueueFifo(x)     do { \
573           CmiLock(CsvAccess(CsdNodeQueueLock));\
574           CqsEnqueueFifo(CsvAccess(CsdNodeQueue),(x)); \
575           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
576         } while(0)
577 #define CsdNodeEnqueueLifo(x)     do { \
578           CmiLock(CsvAccess(CsdNodeQueueLock));\
579           CqsEnqueueLifo(CsvAccess(CsdNodeQueue),(x))); \
580           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
581         } while(0)
582 #define CsdNodeEnqueue(x)     do { \
583           CmiLock(CsvAccess(CsdNodeQueueLock));\
584           CqsEnqueueFifo(CsvAccess(CsdNodeQueue),(x));\
585           CmiUnlock(CsvAccess(CsdNodeQueueLock)); \
586         } while(0)
587
588 #define CsdNodeEmpty()            (CqsEmpty(CpvAccess(CsdNodeQueue)))
589 #define CsdNodeLength()           (CqsLength(CpvAccess(CsdNodeQueue)))
590
591 #else
592
593 #define CsdNodeEnqueueGeneral(x,s,i,p) (CsdEnqueueGeneral(x,s,i,p))
594 #define CsdNodeEnqueueFifo(x) (CqsEnqueueFifo(CpvAccess(CsdSchedQueue),(x)))
595 #define CsdNodeEnqueueLifo(x) (CqsEnqueueLifo(CpvAccess(CsdSchedQueue),(x)))
596 #define CsdNodeEnqueue(x)     (CsdEnqueue(x))
597 #define CsdNodeEmpty()        (CqsEmpty(CpvAccess(CsdSchedQueue)))
598 #define CsdNodeLength()       (CqsLength(CpvAccess(CsdSchedQueue)))
599
600 #endif
601
602 #define CsdEnqueueGeneral(x,s,i,p)\
603     (CqsEnqueueGeneral(CpvAccess(CsdSchedQueue),(x),(s),(i),(p)))
604 #define CsdEnqueueFifo(x)     (CqsEnqueueFifo(CpvAccess(CsdSchedQueue),(x)))
605 #define CsdEnqueueLifo(x)     (CqsEnqueueLifo(CpvAccess(CsdSchedQueue),(x)))
606 #define CsdEnqueue(x)         (CqsEnqueueFifo(CpvAccess(CsdSchedQueue),(x)))
607 #define CsdEmpty()            (CqsEmpty(CpvAccess(CsdSchedQueue)))
608 #define CsdLength()           (CqsLength(CpvAccess(CsdSchedQueue)))
609
610 #if CMK_CMIPRINTF_IS_A_BUILTIN /* these are implemented in machine.c */
611 void  CmiPrintf(const char *, ...);
612 void  CmiError(const char *, ...);
613 int   CmiScanf(const char *, ...);
614
615 #else /* standard definitions */
616
617 #include <stdio.h>
618
619 /*
620  * I made vprintf functions for CmiPrintf and CmiError, but on the
621  * O2K, there is no equivalent vscanf!
622
623  #define CmiPrintf printf
624  #define CmiError  printf
625 */
626 #include <stdarg.h>
627
628 void  CmiPrintf(const char *format, ...);
629 void  CmiError(const char *format, ...);
630 #define CmiScanf  scanf
631
632 #endif
633
634 #ifdef CMK_OPTIMIZE
635 #define CmiAssert(expr) ((void) 0)
636 #else
637 #if defined(__STDC__) || defined(__cplusplus)
638 #define __CMK_STRING(x) #x
639 #else
640 #define __CMK_STRING(x) "x"
641 #endif
642 extern void __cmi_assert(const char *, const char *, int);
643 #define CmiAssert(expr) \
644   ((void) ((expr) ? 0 :                   \
645      (__cmi_assert (__CMK_STRING(expr), __FILE__, __LINE__), 0)))
646 #endif
647
648 typedef void (*CmiStartFn)(int argc, char **argv);
649
650 /********* CSD - THE SCHEDULER ********/
651
652 CpvExtern(int, _ccd_numchecks);
653 extern void  CcdCallBacks();
654 #define CsdPeriodic() do{ if (CpvAccess(_ccd_numchecks)-- <= 0) CcdCallBacks(); } while(0)
655 #define CsdResetPeriodic()    CpvAccess(_ccd_numchecks) = 0;
656
657 extern void  CsdEndIdle(void);
658 extern void  CsdStillIdle(void);
659 extern void  CsdBeginIdle(void);
660
661 typedef struct {
662   void *localQ;
663   void *nodeQ;
664   void *schedQ;
665   int *localCounter;
666 #if CMK_OBJECT_QUEUE_AVAILABLE
667   void *objQ;
668 #endif
669   CmiNodeLock nodeLock;
670 } CsdSchedulerState_t;
671 extern void CsdSchedulerState_new(CsdSchedulerState_t *state);
672 extern void *CsdNextMessage(CsdSchedulerState_t *state);
673
674 extern void  *CmiGetNonLocal(void);
675 extern void   CmiNotifyIdle(void);
676
677 /*Different kinds of schedulers: generic, eternal, counting, polling*/
678 extern  int CsdScheduler(int maxmsgs);
679 extern void CsdScheduleForever(void);
680 extern  int CsdScheduleCount(int maxmsgs);
681 extern void CsdSchedulePoll(void);
682
683 #define CsdExitScheduler()  (CpvAccess(CsdStopFlag)++)
684
685 #if CMK_SPANTREE_USE_COMMON_CODE
686
687 #define CST_W  (CMK_SPANTREE_MAXSPAN)
688 #define CST_NN (CmiNumNodes())
689 #define CmiNodeSpanTreeParent(n) ((n)?(((n)-1)/CST_W):(-1))
690 #define CmiNodeSpanTreeChildren(n,c) do {\
691           int _i; \
692           for(_i=0; _i<CST_W; _i++) { \
693             int _x = (n)*CST_W+_i+1; \
694             if(_x<CST_NN) (c)[_i]=_x; \
695           }\
696         } while(0)
697 #define CmiNumNodeSpanTreeChildren(n) ((((n)+1)*CST_W<CST_NN)? CST_W : \
698           ((((n)*CST_W+1)>=CST_NN)?0:((CST_NN-1)-(n)*CST_W)))
699 #define CST_R(p) (CmiRankOf(p))
700 #define CST_NF(n) (CmiNodeFirst(n))
701 #define CST_SP(n) (CmiNodeSpanTreeParent(n))
702 #define CST_ND(p) (CmiNodeOf(p))
703 #define CST_NS(p) (CmiNodeSize(CST_ND(p)))
704 #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))
705 #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)))
706 #define CST_SC(p) (CmiNumNodeSpanTreeChildren(CST_ND(p)))
707 #define CmiNumSpanTreeChildren(p) (CST_R(p)?CST_C(p):(CST_SC(p)+CST_C(p)))
708 #define CmiSpanTreeChildren(p,c) do {\
709           int _i,_c=0; \
710           if(CST_R(p)==0) { \
711             for(_i=0;_i<CST_W;_i++) { \
712               int _x = CST_ND(p)*CST_W+_i+1; \
713               if(_x<CST_NN) (c)[_c++]=CST_NF(_x); \
714             }\
715           } \
716           for(_i=0;_i<CST_W;_i++) { \
717             int _x = CST_R(p)*CST_W+_i+1; \
718             if(_x<CST_NS(p)) (c)[_c++]=CST_NF(CST_ND(p))+_x; \
719           }\
720         } while(0)
721
722 #else
723
724 int      CmiNumSpanTreeChildren(int) ;
725 int      CmiSpanTreeParent(int) ;
726 void     CmiSpanTreeChildren(int node, int *children);
727 int      CmiNumNodeSpanTreeChildren(int);
728 int      CmiNodeSpanTreeParent(int) ;
729 void     CmiNodeSpanTreeChildren(int node, int *children) ;
730 #endif
731
732 /****** MULTICAST GROUPS ******/
733
734 typedef CMK_MULTICAST_GROUP_TYPE CmiGroup;
735
736 void     CmiGroupInit();
737 CmiGroup CmiEstablishGroup(int npes, int *pes);
738 void     CmiLookupGroup(CmiGroup grp, int *npes, int **pes);
739
740 /****** CMI MESSAGE TRANSMISSION ******/
741
742 void          CmiSyncSendFn(int, int, char *);
743 CmiCommHandle CmiAsyncSendFn(int, int, char *);
744 void          CmiFreeSendFn(int, int, char *);
745
746 void          CmiSyncBroadcastFn(int, char *);
747 CmiCommHandle CmiAsyncBroadcastFn(int, char *);
748 void          CmiFreeBroadcastFn(int, char *);
749
750 void          CmiSyncBroadcastAllFn(int, char *);
751 CmiCommHandle CmiAsyncBroadcastAllFn(int, char *);
752 void          CmiFreeBroadcastAllFn(int, char *);
753
754 void          CmiSyncListSendFn(int, int *, int, char*);
755 CmiCommHandle CmiAsyncListSendFn(int, int *, int, char*);
756 void          CmiFreeListSendFn(int, int *, int, char*);
757
758 void          CmiSyncMulticastFn(CmiGroup, int, char*);
759 CmiCommHandle CmiAsyncMulticastFn(CmiGroup, int, char*);
760 void          CmiFreeMulticastFn(CmiGroup, int, char*);
761
762 void          CmiSyncVectorSend(int, int, int *, char **);
763 CmiCommHandle CmiAsyncVectorSend(int, int, int *, char **);
764 void          CmiSyncVectorSendAndFree(int, int, int *, char **);
765 void          CmiMultipleSend(unsigned int, int, int *, char **);
766 void          CmiMultipleIsend(unsigned int, int, int *, char **);
767
768 int           CmiAsyncMsgSent(CmiCommHandle);
769 void          CmiReleaseCommHandle(CmiCommHandle);
770
771 #define CmiSyncSend(p,s,m)              (CmiSyncSendFn((p),(s),(char *)(m)))
772 #define CmiAsyncSend(p,s,m)             (CmiAsyncSendFn((p),(s),(char *)(m)))
773 #define CmiSyncSendAndFree(p,s,m)       (CmiFreeSendFn((p),(s),(char *)(m)))
774
775 #define CmiSyncBroadcast(s,m)           (CmiSyncBroadcastFn((s),(char *)(m)))
776 #define CmiAsyncBroadcast(s,m)          (CmiAsyncBroadcastFn((s),(char *)(m)))
777 #define CmiSyncBroadcastAndFree(s,m)    (CmiFreeBroadcastFn((s),(char *)(m)))
778
779 #define CmiSyncBroadcastAll(s,m)        (CmiSyncBroadcastAllFn((s),(char *)(m)))
780 #define CmiAsyncBroadcastAll(s,m)       (CmiAsyncBroadcastAllFn((s),(char *)(m)))
781 #define CmiSyncBroadcastAllAndFree(s,m) (CmiFreeBroadcastAllFn((s),(char *)(m)))
782
783 #define CmiSyncListSend(n,l,s,m)        (CmiSyncListSendFn((n),(l),(s),(char *)(m)))
784 #define CmiAsyncListSend(n,l,s,m)       (CmiAsyncListSendFn((n),(l),(s),(char *)(m)))
785 #define CmiSyncListSendAndFree(n,l,s,m) (CmiFreeListSendFn((n),(l),(s),(char *)(m)))
786
787 #define CmiSyncMulticast(g,s,m)         (CmiSyncMulticastFn((g),(s),(char*)(m)))
788 #define CmiAsyncMulticast(g,s,m)        (CmiAsyncMulticastFn((g),(s),(char*)(m)))
789 #define CmiSyncMulticastAndFree(g,s,m)  (CmiFreeMulticastFn((g),(s),(char*)(m)))
790
791 #if CMK_NODE_QUEUE_AVAILABLE
792 void          CmiSyncNodeSendFn(int, int, char *);
793 CmiCommHandle CmiAsyncNodeSendFn(int, int, char *);
794 void          CmiFreeNodeSendFn(int, int, char *);
795
796 void          CmiSyncNodeBroadcastFn(int, char *);
797 CmiCommHandle CmiAsyncNodeBroadcastFn(int, char *);
798 void          CmiFreeNodeBroadcastFn(int, char *);
799
800 void          CmiSyncNodeBroadcastAllFn(int, char *);
801 CmiCommHandle CmiAsyncNodeBroadcastAllFn(int, char *);
802 void          CmiFreeNodeBroadcastAllFn(int, char *);
803 #endif
804
805 #if CMK_NODE_QUEUE_AVAILABLE
806 #define CmiSyncNodeSend(p,s,m)          (CmiSyncNodeSendFn((p),(s),(char *)(m)))
807 #define CmiAsyncNodeSend(p,s,m)             (CmiAsyncNodeSendFn((p),(s),(char *)(m)))
808 #define CmiSyncNodeSendAndFree(p,s,m)       (CmiFreeNodeSendFn((p),(s),(char *)(m)))
809 #define CmiSyncNodeBroadcast(s,m)           (CmiSyncNodeBroadcastFn((s),(char *)(m)))
810 #define CmiAsyncNodeBroadcast(s,m)          (CmiAsyncNodeBroadcastFn((s),(char *)(m)))
811 #define CmiSyncNodeBroadcastAndFree(s,m)    (CmiFreeNodeBroadcastFn((s),(char *)(m)))
812 #define CmiSyncNodeBroadcastAll(s,m)        (CmiSyncNodeBroadcastAllFn((s),(char *)(m)))
813 #define CmiAsyncNodeBroadcastAll(s,m)       (CmiAsyncNodeBroadcastAllFn((s),(char *)(m)))
814 #define CmiSyncNodeBroadcastAllAndFree(s,m) (CmiFreeNodeBroadcastAllFn((s),(char *)(m)))
815 #else
816 #define CmiSyncNodeSend(n,s,m)        CmiSyncSend(CmiNodeFirst(n),s,m)
817 #define CmiAsyncNodeSend(n,s,m)       CmiAsyncSend(CmiNodeFirst(n),s,m)
818 #define CmiSyncNodeSendAndFree(n,s,m) CmiSyncSendAndFree(CmiNodeFirst(n),s,m)
819 #define CmiSyncNodeBroadcast(s,m)           do { \
820           int _i; \
821           for(_i=0; _i<CmiNumNodes(); _i++) \
822             if(_i != CmiMyNode()) \
823               CmiSyncSend(CmiNodeFirst(_i),s,m); \
824         } while(0)
825 #define CmiAsyncNodeBroadcast(s,m)          CmiSyncNodeBroadcast(s,m)
826 #define CmiSyncNodeBroadcastAndFree(s,m)    do { \
827           CmiSyncNodeBroadcast(s,m); \
828           CmiFree(m); \
829         } while(0)
830 #define CmiSyncNodeBroadcastAll(s,m)           do { \
831           int _i; \
832           for(_i=0; _i<CmiNumNodes(); _i++) \
833             CmiSyncSend(CmiNodeFirst(_i),s,m); \
834         } while(0)
835 #define CmiAsyncNodeBroadcastAll(s,m)       CmiSyncNodeBroadcastAll(s,m)
836 #define CmiSyncNodeBroadcastAllAndFree(s,m) do { \
837           CmiSyncNodeBroadcastAll(s,m); \
838           CmiFree(m); \
839         } while(0)
840 #endif
841
842 /******** CMI MESSAGE RECEPTION ********/
843
844 void   CmiDeliversInit();
845 int    CmiDeliverMsgs(int maxmsgs);
846 void   CmiDeliverSpecificMsg(int handler);
847 void   CmiHandleMessage(void *msg);
848
849 /******** CQS: THE QUEUEING SYSTEM ********/
850
851 #define CQS_QUEUEING_FIFO 2
852 #define CQS_QUEUEING_LIFO 3
853 #define CQS_QUEUEING_IFIFO 4
854 #define CQS_QUEUEING_ILIFO 5
855 #define CQS_QUEUEING_BFIFO 6
856 #define CQS_QUEUEING_BLIFO 7
857 #define CQS_QUEUEING_LFIFO 8
858 #define CQS_QUEUEING_LLIFO 9
859
860 /****** Isomalloc: Migratable Memory Allocation ********/
861 /*Simple block-by-block interface:*/
862 void *CmiIsomalloc(int sizeInBytes);
863 void  CmiIsomallocPup(pup_er p,void **block);
864 void  CmiIsomallocFree(void *block);
865
866 int   CmiIsomallocLength(void *block);
867 int   CmiIsomallocInRange(void *addr);
868
869 /*List-of-blocks interface:*/
870 struct CmiIsomallocBlockList {/*Circular doubly-linked list of blocks:*/
871         struct CmiIsomallocBlockList *prev,*next;
872         /*actual data of block follows here...*/
873 };
874 typedef struct CmiIsomallocBlockList CmiIsomallocBlockList;
875
876 /*Build/pup/destroy an entire blockList.*/
877 CmiIsomallocBlockList *CmiIsomallocBlockListNew(void);
878 void CmiIsomallocBlockListPup(pup_er p,CmiIsomallocBlockList **l);
879 void CmiIsomallocBlockListDelete(CmiIsomallocBlockList *l);
880
881 /*Allocate/free a block from this blockList*/
882 void *CmiIsomallocBlockListMalloc(CmiIsomallocBlockList *l,int nBytes);
883 void CmiIsomallocBlockListFree(void *doomedMallocedBlock);
884
885 /****** CTH: THE LOW-LEVEL THREADS PACKAGE ******/
886
887 typedef struct CthThreadStruct *CthThread;
888
889 typedef void        (*CthVoidFn)();
890 typedef void        (*CthAwkFn)(CthThread,int,
891                                 int prioBits,unsigned int *prioptr);
892 typedef CthThread   (*CthThFn)();
893
894 int        CthImplemented(void);
895
896 CthThread  CthPup(pup_er, CthThread);
897
898 CthThread  CthSelf(void);
899 CthThread  CthCreate(CthVoidFn, void *, int);
900 CthThread  CthCreateMigratable(CthVoidFn, void *, int);
901 void       CthResume(CthThread);
902 void       CthFree(CthThread);
903
904 void       CthSetSuspendable(CthThread, int);
905 int        CthIsSuspendable(CthThread);
906
907 void       CthSuspend(void);
908 void       CthAwaken(CthThread);
909 void       CthAwakenPrio(CthThread, int, int, unsigned int *);
910 void       CthSetStrategy(CthThread, CthAwkFn, CthThFn);
911 void       CthSetStrategyDefault(CthThread);
912 void       CthYield(void);
913 void       CthYieldPrio(int,int,unsigned int*);
914
915 void       CthSetNext(CthThread t, CthThread next);
916 CthThread  CthGetNext(CthThread t);
917
918 void       CthSwitchThread(CthThread t);
919
920 /* unimplemented: preemptive threads */
921 void       CthAutoYield(CthThread t, int flag);
922 double     CthAutoYieldFreq(CthThread t);
923 void       CthAutoYieldBlock(void);
924 void       CthAutoYieldUnblock(void);
925
926 /* Converse Thread Global (Ctg) global variable manipulation */
927 typedef struct CtgGlobalStruct *CtgGlobals;
928
929 /** Initialize the globals support (called on each processor). */
930 void CtgInit(void);
931
932 /** Copy the current globals into this new set */
933 CtgGlobals CtgCreate(void);
934 /** Install this set of globals. If g==NULL, returns to original globals. */
935 void CtgInstall(CtgGlobals g);
936 /** PUP this (not currently installed) globals set */
937 CtgGlobals CtgPup(pup_er, CtgGlobals g);
938 /** Delete this (not currently installed) set of globals. */
939 void CtgFree(CtgGlobals g);
940 /** Return the current global list */
941 CtgGlobals CtgCurrentGlobals(void);
942
943 /* The thread listener structure. The user must register one such listener
944         if he wants to find out when a thread is suspended or when it starts running
945         or gets destroyed. It can be used for tracing etc.
946 */
947
948 struct CthThreadListener;
949
950 typedef void (*CthThreadListener_suspend)(struct CthThreadListener *l);
951 typedef void (*CthThreadListener_resume)(struct CthThreadListener *l);
952 typedef void (*CthThreadListener_free)(struct CthThreadListener *l);
953
954 struct CthThreadListener {
955        /** This thread is about to block. */
956        CthThreadListener_suspend suspend;
957
958        /** This thread is about to begin execution after blocking. */
959        CthThreadListener_resume resume;
960
961        /** This thread is being destroyed.  */
962        CthThreadListener_free free;
963
964        /** Pointer to listener-specific data (if needed).
965            Set by listener.
966        */
967        void *data;
968
969        /** Pointer to the thread this listener controls.
970            Set by CthAddListener.
971         */
972        CthThread thread;
973
974        /** The next listener, or NULL at end of chain.
975            Set by CthAddListener, and used only by threads.c.
976        */
977        struct CthThreadListener *next;
978 };
979
980 /**
981   This listener is about to begin receiving suspend and
982 resume events for this thread.  "suspend", "resume", "free",
983 and "data" fields must all already be set.  When this thread
984 exits, l->free will be called on this listener, which should
985 deallocate the listener memory.
986 */
987 void CthAddListener(CthThread th,struct CthThreadListener *l);
988
989 /**
990   This is function is inserted into .def.h after thread creation.
991   It serves as an interface for the user to add the listeners 
992   as needed. User has to implement this somewhere in the system.
993 */
994 void CthUserAddListeners(CthThread th);
995
996
997 /****** CTH: THREAD-PRIVATE VARIABLES ******/
998
999 #if CMK_THREADS_REQUIRE_NO_CPV
1000
1001 #define CthCpvDeclare(t,v)    t v
1002 #define CthCpvExtern(t,v)     extern t v
1003 #define CthCpvStatic(t,v)     static t v
1004 #define CthCpvInitialize(t,v) do {} while(0)
1005 #define CthCpvAccess(x)       x
1006
1007 #else
1008
1009 #define CthCpvDeclare(t,v)    CpvDeclare(t,v)
1010 #define CthCpvExtern(t,v)     CpvExtern(t,v)
1011 #define CthCpvStatic(t,v)     CpvStaticDeclare(t,v)
1012 #define CthCpvInitialize(t,v) CpvInitialize(t,v)
1013 #define CthCpvAccess(x)       CpvAccess(x)
1014
1015 #endif
1016
1017 CthCpvExtern(char *,CthData);
1018 extern int CthRegister(int dataSize);
1019 extern void CthRegistered(int dataOffMax);
1020 extern char *CthGetData(CthThread t);
1021
1022 #define CtvDeclare(t,v)         typedef t CtvType##v; CsvDeclare(int,CtvOffs##v)=(-1)
1023 #define CtvStaticDeclare(t,v)   typedef t CtvType##v; CsvStaticDeclare(int,CtvOffs##v)=(-1)
1024 #define CtvExtern(t,v)          typedef t CtvType##v; CsvExtern(int,CtvOffs##v)
1025 #define CtvAccess(v)            (*((CtvType##v *)(CthCpvAccess(CthData)+CsvAccess(CtvOffs##v))))
1026 #define CtvAccessOther(t,v)            (*((CtvType##v *)(CthGetData(t)+CsvAccess(CtvOffs##v))))
1027 #define CtvInitialize(t,v)      do { \
1028         if(CsvAccess(CtvOffs##v)==(-1)) \
1029                 CsvAccess(CtvOffs##v)=CthRegister(sizeof(CtvType##v));\
1030         else CthRegistered(CsvAccess(CtvOffs##v)+sizeof(CtvType##v));\
1031 } while(0)
1032
1033 /****** CFUTURE: CONVERSE FUTURES ******/
1034
1035 typedef struct Cfuture_s
1036 {
1037   int pe;
1038   struct Cfuture_data_s *data;
1039 }
1040 Cfuture;
1041
1042 #define CfutureValueData(v) ((void*)((v)->rest))
1043
1044 Cfuture       CfutureCreate(void);
1045 void          CfutureSet(Cfuture f, void *val, int len);
1046 void         *CfutureWait(Cfuture f);
1047 void          CfutureDestroy(Cfuture f);
1048
1049 void         *CfutureCreateBuffer(int bytes);
1050 void          CfutureDestroyBuffer(void *val);
1051 void          CfutureStoreBuffer(Cfuture f, void *value);
1052
1053 #define       CfuturePE(f) ((f).pe)
1054
1055 void CfutureInit();
1056
1057 /****** CLD: THE LOAD BALANCER ******/
1058
1059 #define CLD_ANYWHERE (-1)
1060 #define CLD_BROADCAST (-2)
1061 #define CLD_BROADCAST_ALL (-3)
1062
1063 typedef void (*CldPackFn)(void *msg);
1064
1065 typedef void (*CldInfoFn)(void *msg, 
1066                           CldPackFn *packer,
1067                           int *len,
1068                           int *queueing,
1069                           int *priobits, 
1070                           unsigned int **prioptr);
1071
1072 typedef int (*CldEstimator)(void);
1073
1074 int CldRegisterInfoFn(CldInfoFn fn);
1075 int CldRegisterPackFn(CldPackFn fn);
1076 void CldRegisterEstimator(CldEstimator fn);
1077 int CldEstimate(void);
1078 char *CldGetStrategy(void);
1079
1080 void CldEnqueue(int pe, void *msg, int infofn);
1081 void CldEnqueueMulti(int npes, int *pes, void *msg, int infofn);
1082 void CldNodeEnqueue(int node, void *msg, int infofn);
1083
1084 /****** CMM: THE MESSAGE MANAGER ******/
1085
1086 typedef struct CmmTableStruct *CmmTable;
1087
1088 #define CmmWildCard (-1)
1089
1090 typedef void (*CmmPupMessageFn)(pup_er p,void **msg);
1091 CmmTable CmmPup(pup_er p, CmmTable t, CmmPupMessageFn msgpup);
1092
1093 CmmTable   CmmNew();
1094 void       CmmFree(CmmTable t);
1095 void       CmmPut(CmmTable t, int ntags, int *tags, void *msg);
1096 void      *CmmFind(CmmTable t, int ntags, int *tags, int *returntags, int del);
1097 int        CmmEntries(CmmTable t);
1098 int        CmmGetLastTag(CmmTable t, int ntags, int *tags);
1099 #define    CmmGet(t,nt,tg,rt)   (CmmFind((t),(nt),(tg),(rt),1))
1100 #define    CmmProbe(t,nt,tg,rt) (CmmFind((t),(nt),(tg),(rt),0))
1101
1102 /******** ConverseInit and ConverseExit ********/
1103
1104 void ConverseInit(int, char**, CmiStartFn, int, int);
1105 void ConverseExit(void);
1106
1107 void CmiAbort(const char *);
1108 void CmiOutOfMemory(int nBytes);
1109
1110 #if CMK_MEMCHECK_OFF
1111 #define _MEMCHECK(p) do{}while(0)
1112 #else
1113 #define _MEMCHECK(p) do { \
1114                          if ((p)==0) CmiOutOfMemory(-1);\
1115                      } while(0)
1116 #endif
1117
1118 /******** CONVCONDS ********/
1119
1120 typedef void (*CcdVoidFn)(void *userParam,double curWallTime);
1121
1122 /*CPU conditions*/
1123 #define CcdPROCESSOR_BEGIN_BUSY 0
1124 #define CcdPROCESSOR_END_IDLE 0 /*Synonym*/
1125 #define CcdPROCESSOR_BEGIN_IDLE 1
1126 #define CcdPROCESSOR_END_BUSY 1 /*Synonym*/
1127 #define CcdPROCESSOR_STILL_IDLE 2
1128
1129 /*Periodic calls*/
1130 #define CcdPERIODIC       16 /*every few ms*/
1131 #define CcdPERIODIC_10ms  17 /*every 10ms (100Hz)*/
1132 #define CcdPERIODIC_100ms 18 /*every 100ms (10Hz)*/
1133 #define CcdPERIODIC_1second  19 /*every second*/
1134 #define CcdPERIODIC_1s       19 /*every second*/
1135 #define CcdPERIODIC_10second 20 /*every 10 seconds*/
1136 #define CcdPERIODIC_10seconds 20 /*every 10 seconds*/
1137 #define CcdPERIODIC_10s      20 /*every 10 seconds*/
1138 #define CcdPERIODIC_1minute  21 /*every minute*/
1139 #define CcdPERIODIC_10minute 22 /*every 10 minutes*/
1140 #define CcdPERIODIC_1hour    23 /*every hour*/
1141 #define CcdPERIODIC_12hour   24 /*every 12 hours*/
1142 #define CcdPERIODIC_1day     25 /*every day*/
1143
1144 /*Other conditions*/
1145 #define CcdQUIESCENCE 30
1146 #define CcdSIGUSR1 32+1
1147 #define CcdSIGUSR2 32+2
1148
1149 /*User-defined conditions start here*/
1150 #define CcdUSER    48
1151
1152 #define CcdIGNOREPE   -2
1153 #if CMK_CONDS_USE_SPECIAL_CODE
1154 typedef int (*CmiSwitchToPEFnPtr)(int pe);
1155 extern CmiSwitchToPEFnPtr CmiSwitchToPE;
1156 #else
1157 #define CmiSwitchToPE(pe)  pe
1158 #endif
1159 void CcdCallFnAfter(CcdVoidFn fnp, void *arg, double msecs);
1160 int CcdCallOnCondition(int condnum, CcdVoidFn fnp, void *arg);
1161 int CcdCallOnConditionKeep(int condnum, CcdVoidFn fnp, void *arg);
1162 void CcdCallFnAfterOnPE(CcdVoidFn fnp, void *arg, double msecs, int pe);
1163 int CcdCallOnConditionOnPE(int condnum, CcdVoidFn fnp, void *arg, int pe);
1164 int CcdCallOnConditionKeepOnPE(int condnum, CcdVoidFn fnp, void *arg, int pe);
1165 void CcdCancelCallOnCondition(int condnum, int idx);
1166 void CcdCancelCallOnConditionKeep(int condnum, int idx);
1167 void CcdRaiseCondition(int condnum);
1168
1169 /* Command-Line-Argument handling */
1170 void CmiArgGroup(const char *parentName,const char *groupName);
1171 int CmiGetArgInt(char **argv,const char *arg,int *optDest);
1172 int CmiGetArgIntDesc(char **argv,const char *arg,int *optDest,const char *desc);
1173 int CmiGetArgDouble(char **argv,const char *arg,double *optDest);
1174 int CmiGetArgDoubleDesc(char **argv,const char *arg,double *optDest,const char *desc);
1175 int CmiGetArgString(char **argv,const char *arg,char **optDest);
1176 int CmiGetArgStringDesc(char **argv,const char *arg,char **optDest,const char *desc);
1177 int CmiGetArgFlag(char **argv,const char *arg);
1178 int CmiGetArgFlagDesc(char **argv,const char *arg,const char *desc);
1179 void CmiDeleteArgs(char **argv,int k);
1180 int CmiGetArgc(char **argv);
1181 char **CmiCopyArgs(char **argv);
1182 int CmiArgGivingUsage(void);
1183
1184 /** 
1185    Extract the function-return pointers listed in the stack
1186    up to this depth.  nSkip is the number of enclosing functions
1187    to skip-- for example, nSkip==0 means the retPtrs[0]
1188    will be the caller of CmiBacktraceRecord.  
1189    Returns retPtrs[0..*nLevels-1] stack pointers.
1190    *nLevels may be decreased if not enough levels are available.
1191  */
1192 void CmiBacktraceRecord(void **retPtrs,int nSkip,int *nLevels);
1193
1194 /** Look up the names of these function pointers.
1195 Caller must free() the returned array, but not the individual
1196 strings.
1197 */
1198 char **CmiBacktraceLookup(void **srcPtrs,int nLevels);
1199
1200 /** Print out the names of these function pointers. */
1201 void CmiBacktracePrint(void **retPtrs,int nLevels);
1202
1203 /* Print (to stdout) the names of the functions that have been 
1204    called up to this point. nSkip is the number of routines on the
1205    top of the stack to *not* print out. */
1206 void CmiPrintStackTrace(int nSkip);
1207
1208 #if CMK_CMIDELIVERS_USE_COMMON_CODE
1209 CpvExtern(void*, CmiLocalQueue);
1210 #endif
1211
1212 char *CmiCopyMsg(char *msg, int len);
1213
1214 /******** Hypercube broadcast propagation (Binomial tree) ********/
1215
1216 /*
1217   This routing will receive a number k containing the dimension in the hypercube
1218   to be used for the broadcast, i.e. k=0 means sending only to MyPe^1, k=1 means
1219   sending to MyPe^2 and MyPe^1, etc.
1220   The array dest_pes will be filled with the id of the processors to which send,
1221   it has to be already allocated, the size should be at least k+1 to allow
1222   enough space.
1223   It return the number of processors to which send, i.e. the size of dest_pes.
1224   This may be less than k+1 due to not complete hypercubes.
1225   For example with pow(2,n)+2 procs and 0 broadcasting, proc pow(2,n) will
1226   receive from 0 in the first step but then it has only proc pow(2,n)+1 as
1227   destination, so most of the other dimentions will be skipped.
1228 */
1229 int HypercubeGetBcastDestinations(int mype, int total_pes, int k, int *dest_pes);
1230
1231 /******** Immediate Messages ********/
1232
1233 CpvExtern(int, CmiImmediateMsgHandlerIdx);
1234
1235
1236 CpvExtern(int, networkProgressCount);
1237 extern int networkProgressPeriod;
1238
1239 #if !CMK_MACHINE_PROGRESS_DEFINED
1240 #define CmiNetworkProgress() 
1241 #define CmiNetworkProgressAfter(p) 
1242
1243 void CmiProbeImmediateMsg();
1244
1245 #else
1246 void CmiMachineProgressImpl();
1247
1248 #define CmiProbeImmediateMsg CmiMachineProgressImpl
1249
1250 #define CmiNetworkProgress() {CpvAccess(networkProgressCount) ++; \
1251       if(CpvAccess(networkProgressCount) ==  networkProgressPeriod) { \
1252           CmiMachineProgressImpl(); \
1253           CpvAccess(networkProgressCount) = 0; \
1254       } \
1255 } \
1256
1257 #define CmiNetworkProgressAfter(p) {CpvAccess(networkProgressCount) ++; \
1258       if(CpvAccess(networkProgressCount) ==  p) { \
1259           CmiMachineProgressImpl(); \
1260           CpvAccess(networkProgressCount) = 0; \
1261       } \
1262 } \
1263
1264 #endif
1265
1266 /*
1267    to immediate-fy a Converse message, set the most significant bit to 1
1268    in the Converse handler (x|0x8000). 
1269 */
1270 #if CMK_IMMEDIATE_MSG
1271 void CmiDelayImmediate();
1272 #  define CmiBecomeImmediate(msg) do { \
1273         CmiSetHandler(msg, (CmiGetHandler(msg))|0x8000); \
1274      } while (0)
1275 #  define CmiIsImmediate(msg)      ((CmiGetHandler(msg)) & 0x8000) 
1276 #  define CmiImmediateHandler(msg) ((CmiGetHandler(msg)) ^ 0x8000)
1277 /*
1278 #  define CmiIsImmediate(msg)   ((CmiGetHandler(msg) == CpvAccessOther(CmiImmediateMsgHandlerIdx,0)))
1279 #  define CmiBecomeImmediate(msg) do {\
1280         CmiSetXHandler(msg,CmiGetHandler(msg)); \
1281         CmiSetHandler(msg,CpvAccessOther(CmiImmediateMsgHandlerIdx,0)); \
1282      } while (0)
1283 #  define CmiImemdiateHandler(msg) (CmiGetXHandler(msg))
1284 */
1285 /* 
1286   for non smp and non intr based version, it returns _immRunning
1287   for smp, this doesnot matter - CkMyPe() comparasion normaly fails and
1288            non threadsafe CqsEnqueueGeneral is avoided.
1289 */
1290 #if CMK_NET_VERSION && ! CMK_SMP
1291 extern int _immRunning;
1292 #  define CmiImmIsRunning()        (_immRunning)
1293 #else
1294 #  define CmiImmIsRunning()        (0)
1295 #endif
1296
1297 #else
1298 #  define CmiBecomeImmediate(msg) /* empty */
1299 #  define CmiIsImmediate(msg)   (0)
1300 #  define CmiImmIsRunning()       (0)
1301 #endif
1302
1303 /******** Performance Counters ********/
1304 void CmiInitCounters();
1305 void CmiStartCounters(int events[], int numEvents);
1306 void CmiStopCounters(int events[], CMK_TYPEDEF_INT8 values[], int numEvents);
1307
1308 /******** Trace ********/
1309
1310 /* this is the type for thread ID, mainly used for projection. */
1311 typedef struct {
1312 int id[3];
1313 } CmiObjId;
1314
1315 /* public interface for thread id acquisition */
1316 CmiObjId *CthGetThreadID(CthThread th);
1317 void CthSetThreadID(CthThread th, int a, int b, int c);
1318
1319 void CthTraceResume(CthThread t);
1320
1321 #include "conv-cpm.h"
1322 #include "conv-cpath.h"
1323 #include "conv-qd.h"
1324 #include "conv-random.h"
1325 #include "conv-lists.h"
1326 #include "conv-trace.h"
1327 #include "persistent.h"
1328
1329 #if defined(__cplusplus)
1330 }
1331 #endif
1332
1333 #include "debug-conv.h"
1334
1335
1336 #endif /* CONVERSE_H */