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