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