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