Improving documentation for scheduling routines.
[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  CmiIsomallocPup(pup_er p,void **block);
1127 void  CmiIsomallocFree(void *block);
1128 int   CmiIsomallocEnabled();
1129
1130 CmiInt8   CmiIsomallocLength(void *block);
1131 int   CmiIsomallocInRange(void *addr);
1132
1133 /*List-of-blocks interface:*/
1134 struct CmiIsomallocBlockList {/*Circular doubly-linked list of blocks:*/
1135         struct CmiIsomallocBlockList *prev,*next;
1136         /*actual data of block follows here...*/
1137 };
1138 typedef struct CmiIsomallocBlockList CmiIsomallocBlockList;
1139
1140 /*Build/pup/destroy an entire blockList.*/
1141 CmiIsomallocBlockList *CmiIsomallocBlockListNew(void);
1142 void CmiIsomallocBlockListPup(pup_er p,CmiIsomallocBlockList **l);
1143 void CmiIsomallocBlockListDelete(CmiIsomallocBlockList *l);
1144
1145 /*Allocate/free a block from this blockList*/
1146 void *CmiIsomallocBlockListMalloc(CmiIsomallocBlockList *l,int nBytes);
1147 void CmiIsomallocBlockListFree(void *doomedMallocedBlock);
1148
1149 /****** CTH: THE LOW-LEVEL THREADS PACKAGE ******/
1150
1151 typedef struct CthThreadStruct *CthThread;
1152 typedef struct {
1153   /*Start with a message header so threads can be enqueued 
1154     as messages (e.g., by CthEnqueueNormalThread in convcore.c)
1155   */
1156   char cmicore[CmiReservedHeaderSize];
1157   CthThread thread;
1158 } CthThreadToken;
1159
1160 CthThreadToken *CthGetToken(CthThread);
1161
1162 typedef void        (*CthVoidFn)();
1163 typedef void        (*CthAwkFn)(CthThreadToken *,int,
1164                                 int prioBits,unsigned int *prioptr);
1165 typedef CthThread   (*CthThFn)();
1166
1167 int        CthImplemented(void);
1168
1169 int        CthMigratable();
1170 CthThread  CthPup(pup_er, CthThread);
1171
1172 CthThread  CthSelf(void);
1173 CthThread  CthCreate(CthVoidFn, void *, int);
1174 CthThread  CthCreateMigratable(CthVoidFn, void *, int);
1175 void       CthResume(CthThread);
1176 void       CthFree(CthThread);
1177
1178 void       CthSetSuspendable(CthThread, int);
1179 int        CthIsSuspendable(CthThread);
1180
1181 /* added for bigsim out-of-core emulation */
1182 void       CthPrintThdMagic(CthThread); 
1183 void       CthPrintThdStack(CthThread);
1184
1185 void       CthSuspend(void);
1186 void       CthAwaken(CthThread);
1187 void       CthAwakenPrio(CthThread, int, int, unsigned int *);
1188 void       CthSetStrategy(CthThread, CthAwkFn, CthThFn);
1189 void       CthSetStrategyDefault(CthThread);
1190 void       CthYield(void);
1191 void       CthYieldPrio(int,int,unsigned int*);
1192
1193 void       CthSetNext(CthThread t, CthThread next);
1194 CthThread  CthGetNext(CthThread t);
1195
1196 void       CthSwitchThread(CthThread t);
1197
1198 size_t     CthStackOffset(CthThread t, char *p);
1199 char     * CthPointer(CthThread t, size_t pos);
1200
1201 /* unimplemented: preemptive threads */
1202 void       CthAutoYield(CthThread t, int flag);
1203 double     CthAutoYieldFreq(CthThread t);
1204 void       CthAutoYieldBlock(void);
1205 void       CthAutoYieldUnblock(void);
1206
1207 /* Converse Thread Global (Ctg) global variable manipulation */
1208 typedef struct CtgGlobalStruct *CtgGlobals;
1209
1210 /** Initialize the globals support (called on each processor). */
1211 void CtgInit(void);
1212 /** PIC method used: 0 = nop, 1 = elfgot, 2 = elfcopy */
1213 CpvExtern(int, CmiPICMethod);
1214
1215 /** Copy the current globals into this new set */
1216 CtgGlobals CtgCreate(void);
1217 /** Install this set of globals. If g==NULL, returns to original globals. */
1218 void CtgInstall(CtgGlobals g);
1219 /** PUP this (not currently installed) globals set */
1220 CtgGlobals CtgPup(pup_er, CtgGlobals g);
1221 /** Delete this (not currently installed) set of globals. */
1222 void CtgFree(CtgGlobals g);
1223 /** Return the current global list */
1224 CtgGlobals CtgCurrentGlobals(void);
1225 void CtgInstall_var(CtgGlobals g, void *ptr);
1226 void CtgUninstall_var(CtgGlobals g, void *ptr);
1227
1228 /* The thread listener structure. The user must register one such listener
1229         if he wants to find out when a thread is suspended or when it starts running
1230         or gets destroyed. It can be used for tracing etc.
1231 */
1232
1233 struct CthThreadListener;
1234
1235 typedef void (*CthThreadListener_suspend)(struct CthThreadListener *l);
1236 typedef void (*CthThreadListener_resume)(struct CthThreadListener *l);
1237 typedef void (*CthThreadListener_free)(struct CthThreadListener *l);
1238
1239 struct CthThreadListener {
1240        /** This thread is about to block. */
1241        CthThreadListener_suspend suspend;
1242
1243        /** This thread is about to begin execution after blocking. */
1244        CthThreadListener_resume resume;
1245
1246        /** This thread is being destroyed.  */
1247        CthThreadListener_free free;
1248
1249        /** Pointer to listener-specific data (if needed).
1250            Set by listener.
1251        */
1252        void *data;
1253
1254        /** Pointer to the thread this listener controls.
1255            Set by CthAddListener.
1256         */
1257        CthThread thread;
1258
1259        /** The next listener, or NULL at end of chain.
1260            Set by CthAddListener, and used only by threads.c.
1261        */
1262        struct CthThreadListener *next;
1263 };
1264
1265 /**
1266   This listener is about to begin receiving suspend and
1267 resume events for this thread.  "suspend", "resume", "free",
1268 and "data" fields must all already be set.  When this thread
1269 exits, l->free will be called on this listener, which should
1270 deallocate the listener memory.
1271 */
1272 void CthAddListener(CthThread th,struct CthThreadListener *l);
1273
1274 /**
1275   This is function is inserted into .def.h after thread creation.
1276   It serves as an interface for the user to add the listeners 
1277   as needed. User has to implement this somewhere in the system.
1278 */
1279 void CthUserAddListeners(CthThread th);
1280
1281
1282 /****** CTH: THREAD-PRIVATE VARIABLES ******/
1283
1284 #if CMK_THREADS_REQUIRE_NO_CPV
1285
1286 #define CthCpvDeclare(t,v)    t v
1287 #define CthCpvExtern(t,v)     extern t v
1288 #define CthCpvStatic(t,v)     static t v
1289 #define CthCpvInitialize(t,v) do {} while(0)
1290 #define CthCpvAccess(x)       x
1291
1292 #else
1293
1294 #define CthCpvDeclare(t,v)    CpvDeclare(t,v)
1295 #define CthCpvExtern(t,v)     CpvExtern(t,v)
1296 #define CthCpvStatic(t,v)     CpvStaticDeclare(t,v)
1297 #define CthCpvInitialize(t,v) CpvInitialize(t,v)
1298 #define CthCpvAccess(x)       CpvAccess(x)
1299
1300 #endif
1301
1302 CthCpvExtern(char *,CthData);
1303 extern int CthRegister(int dataSize);
1304 extern void CthRegistered(int dataOffMax);
1305 extern char *CthGetData(CthThread t);
1306
1307 #define CtvDeclare(t,v)         typedef t CtvType##v; CsvDeclare(int,CtvOffs##v)=(-1)
1308 #define CtvStaticDeclare(t,v)   typedef t CtvType##v; CsvStaticDeclare(int,CtvOffs##v)=(-1)
1309 #define CtvExtern(t,v)          typedef t CtvType##v; CsvExtern(int,CtvOffs##v)
1310 #define CtvAccess(v)            (*((CtvType##v *)(CthCpvAccess(CthData)+CsvAccess(CtvOffs##v))))
1311 #define CtvAccessOther(t,v)            (*((CtvType##v *)(CthGetData(t)+CsvAccess(CtvOffs##v))))
1312 #define CtvInitialize(t,v)      do { \
1313         if(CsvAccess(CtvOffs##v)==(-1)) \
1314                 CsvAccess(CtvOffs##v)=CthRegister(sizeof(CtvType##v));\
1315         else CthRegistered(CsvAccess(CtvOffs##v)+sizeof(CtvType##v));\
1316 } while(0)
1317
1318 /****** CFUTURE: CONVERSE FUTURES ******/
1319
1320 typedef struct Cfuture_s
1321 {
1322   int pe;
1323   struct Cfuture_data_s *data;
1324 }
1325 Cfuture;
1326
1327 #define CfutureValueData(v) ((void*)((v)->rest))
1328
1329 Cfuture       CfutureCreate(void);
1330 void          CfutureSet(Cfuture f, void *val, int len);
1331 void         *CfutureWait(Cfuture f);
1332 void          CfutureDestroy(Cfuture f);
1333
1334 void         *CfutureCreateBuffer(int bytes);
1335 void          CfutureDestroyBuffer(void *val);
1336 void          CfutureStoreBuffer(Cfuture f, void *value);
1337
1338 #define       CfuturePE(f) ((f).pe)
1339
1340 void CfutureInit();
1341
1342 /****** CLD: THE LOAD BALANCER ******/
1343
1344 #define CLD_ANYWHERE (-1)
1345 #define CLD_BROADCAST (-2)
1346 #define CLD_BROADCAST_ALL (-3)
1347
1348 typedef void (*CldPackFn)(void *msg);
1349
1350 typedef void (*CldInfoFn)(void *msg, 
1351                           CldPackFn *packer,
1352                           int *len,
1353                           int *queueing,
1354                           int *priobits, 
1355                           unsigned int **prioptr);
1356
1357 typedef int (*CldEstimator)(void);
1358
1359 int CldRegisterInfoFn(CldInfoFn fn);
1360 int CldRegisterPackFn(CldPackFn fn);
1361 void CldRegisterEstimator(CldEstimator fn);
1362 int CldEstimate(void);
1363 char *CldGetStrategy(void);
1364
1365 void CldEnqueue(int pe, void *msg, int infofn);
1366 void CldEnqueueMulti(int npes, int *pes, void *msg, int infofn);
1367 void CldNodeEnqueue(int node, void *msg, int infofn);
1368
1369 /****** CMM: THE MESSAGE MANAGER ******/
1370
1371 typedef struct CmmTableStruct *CmmTable;
1372
1373 #define CmmWildCard (-1)
1374
1375 typedef void (*CmmPupMessageFn)(pup_er p,void **msg);
1376 CmmTable CmmPup(pup_er p, CmmTable t, CmmPupMessageFn msgpup);
1377
1378 CmmTable   CmmNew();
1379 void       CmmFree(CmmTable t);
1380 void       CmmFreeAll(CmmTable t);
1381 void       CmmPut(CmmTable t, int ntags, int *tags, void *msg);
1382 void      *CmmFind(CmmTable t, int ntags, int *tags, int *returntags, int del);
1383 int        CmmEntries(CmmTable t);
1384 int        CmmGetLastTag(CmmTable t, int ntags, int *tags);
1385 #define    CmmGet(t,nt,tg,rt)   (CmmFind((t),(nt),(tg),(rt),1))
1386 #define    CmmProbe(t,nt,tg,rt) (CmmFind((t),(nt),(tg),(rt),0))
1387
1388 /******** ConverseInit and ConverseExit ********/
1389
1390 void ConverseInit(int, char**, CmiStartFn, int, int);
1391 void ConverseExit(void);
1392
1393 void CmiAbort(const char *);
1394 void CmiOutOfMemory(int nBytes);
1395
1396 #if CMK_MEMCHECK_OFF
1397 #define _MEMCHECK(p) do{}while(0)
1398 #else
1399 #define _MEMCHECK(p) do { \
1400                          if ((p)==0) CmiOutOfMemory(-1);\
1401                      } while(0)
1402 #endif
1403
1404 /******** CONVCONDS ********/
1405
1406 typedef void (*CcdVoidFn)(void *userParam,double curWallTime);
1407
1408 /*CPU conditions*/
1409 #define CcdPROCESSOR_BEGIN_BUSY 0
1410 #define CcdPROCESSOR_END_IDLE 0 /*Synonym*/
1411 #define CcdPROCESSOR_BEGIN_IDLE 1
1412 #define CcdPROCESSOR_END_BUSY 1 /*Synonym*/
1413 #define CcdPROCESSOR_STILL_IDLE 2
1414
1415 /*Periodic calls*/
1416 #define CcdPERIODIC       16 /*every few ms*/
1417 #define CcdPERIODIC_10ms  17 /*every 10ms (100Hz)*/
1418 #define CcdPERIODIC_100ms 18 /*every 100ms (10Hz)*/
1419 #define CcdPERIODIC_1second  19 /*every second*/
1420 #define CcdPERIODIC_1s       19 /*every second*/
1421 #define CcdPERIODIC_10second 20 /*every 10 seconds*/
1422 #define CcdPERIODIC_10seconds 20 /*every 10 seconds*/
1423 #define CcdPERIODIC_10s      20 /*every 10 seconds*/
1424 #define CcdPERIODIC_1minute  21 /*every minute*/
1425 #define CcdPERIODIC_10minute 22 /*every 10 minutes*/
1426 #define CcdPERIODIC_1hour    23 /*every hour*/
1427 #define CcdPERIODIC_12hour   24 /*every 12 hours*/
1428 #define CcdPERIODIC_1day     25 /*every day*/
1429
1430 /*Other conditions*/
1431 #define CcdQUIESCENCE 30
1432 #define CcdSIGUSR1 32+1
1433 #define CcdSIGUSR2 32+2
1434
1435 /*User-defined conditions start here*/
1436 #define CcdUSER    48
1437
1438 #define CcdIGNOREPE   -2
1439 #if CMK_CONDS_USE_SPECIAL_CODE
1440 typedef int (*CmiSwitchToPEFnPtr)(int pe);
1441 extern CmiSwitchToPEFnPtr CmiSwitchToPE;
1442 #else
1443 #define CmiSwitchToPE(pe)  pe
1444 #endif
1445 void CcdCallFnAfter(CcdVoidFn fnp, void *arg, double msecs);
1446 int CcdCallOnCondition(int condnum, CcdVoidFn fnp, void *arg);
1447 int CcdCallOnConditionKeep(int condnum, CcdVoidFn fnp, void *arg);
1448 void CcdCallFnAfterOnPE(CcdVoidFn fnp, void *arg, double msecs, int pe);
1449 int CcdCallOnConditionOnPE(int condnum, CcdVoidFn fnp, void *arg, int pe);
1450 int CcdCallOnConditionKeepOnPE(int condnum, CcdVoidFn fnp, void *arg, int pe);
1451 void CcdCancelCallOnCondition(int condnum, int idx);
1452 void CcdCancelCallOnConditionKeep(int condnum, int idx);
1453 void CcdRaiseCondition(int condnum);
1454
1455 /* Command-Line-Argument handling */
1456 void CmiArgGroup(const char *parentName,const char *groupName);
1457 int CmiGetArgInt(char **argv,const char *arg,int *optDest);
1458 int CmiGetArgIntDesc(char **argv,const char *arg,int *optDest,const char *desc);
1459 int CmiGetArgDouble(char **argv,const char *arg,double *optDest);
1460 int CmiGetArgDoubleDesc(char **argv,const char *arg,double *optDest,const char *desc);
1461 int CmiGetArgString(char **argv,const char *arg,char **optDest);
1462 int CmiGetArgStringDesc(char **argv,const char *arg,char **optDest,const char *desc);
1463 int CmiGetArgFlag(char **argv,const char *arg);
1464 int CmiGetArgFlagDesc(char **argv,const char *arg,const char *desc);
1465 void CmiDeleteArgs(char **argv,int k);
1466 int CmiGetArgc(char **argv);
1467 char **CmiCopyArgs(char **argv);
1468 int CmiArgGivingUsage(void);
1469
1470 /** 
1471    Extract the function-return pointers listed in the stack
1472    up to this depth.  nSkip is the number of enclosing functions
1473    to skip-- for example, nSkip==0 means the retPtrs[0]
1474    will be the caller of CmiBacktraceRecord.  
1475    Returns retPtrs[0..*nLevels-1] stack pointers.
1476    *nLevels may be decreased if not enough levels are available.
1477  */
1478 void CmiBacktraceRecord(void **retPtrs,int nSkip,int *nLevels);
1479
1480 /** Look up the names of these function pointers.
1481 Caller must free() the returned array, but not the individual
1482 strings.
1483 */
1484 char **CmiBacktraceLookup(void **srcPtrs,int nLevels);
1485
1486 /** Print out the names of these function pointers. */
1487 void CmiBacktracePrint(void **retPtrs,int nLevels);
1488
1489 /* Print (to stdout) the names of the functions that have been 
1490    called up to this point. nSkip is the number of routines on the
1491    top of the stack to *not* print out. */
1492 void CmiPrintStackTrace(int nSkip);
1493 int CmiIsFortranLibraryCall();
1494
1495 #if CMK_CMIDELIVERS_USE_COMMON_CODE
1496 CpvExtern(void*, CmiLocalQueue);
1497 #endif
1498
1499 char *CmiCopyMsg(char *msg, int len);
1500
1501 /******** Hypercube broadcast propagation (Binomial tree) ********/
1502
1503 /*
1504   This routing will receive a number k containing the dimension in the hypercube
1505   to be used for the broadcast, i.e. k=0 means sending only to MyPe^1, k=1 means
1506   sending to MyPe^2 and MyPe^1, etc.
1507   The array dest_pes will be filled with the id of the processors to which send,
1508   it has to be already allocated, the size should be at least k+1 to allow
1509   enough space.
1510   It return the number of processors to which send, i.e. the size of dest_pes.
1511   This may be less than k+1 due to not complete hypercubes.
1512   For example with pow(2,n)+2 procs and 0 broadcasting, proc pow(2,n) will
1513   receive from 0 in the first step but then it has only proc pow(2,n)+1 as
1514   destination, so most of the other dimentions will be skipped.
1515 */
1516 int HypercubeGetBcastDestinations(int mype, int total_pes, int k, int *dest_pes);
1517
1518 /******** Immediate Messages ********/
1519
1520 CpvExtern(int, CmiImmediateMsgHandlerIdx);
1521
1522
1523 CpvExtern(unsigned, networkProgressCount);
1524 extern int networkProgressPeriod;
1525
1526 #if !CMK_MACHINE_PROGRESS_DEFINED
1527
1528 #define CmiNetworkProgress() 
1529 #define CmiNetworkProgressAfter(p) 
1530 #define CmiMachineProgressImpl()
1531
1532 #else
1533
1534 /*#ifdef __cplusplus
1535 extern "C" 
1536 #endif*/
1537 void CmiMachineProgressImpl();
1538
1539 #define CmiNetworkProgress() {CpvAccess(networkProgressCount) ++; \
1540       if(CpvAccess(networkProgressCount) >=  networkProgressPeriod) { \
1541           CmiMachineProgressImpl(); \
1542           CpvAccess(networkProgressCount) = 0; \
1543       } \
1544 } \
1545
1546 #define CmiNetworkProgressAfter(p) {CpvAccess(networkProgressCount) ++; \
1547       if(CpvAccess(networkProgressCount) >=  p) { \
1548           CmiMachineProgressImpl(); \
1549           CpvAccess(networkProgressCount) = 0; \
1550       } \
1551 } \
1552
1553 #endif
1554
1555 #define CmiProbeImmediateMsg CmiMachineProgressImpl
1556
1557 /*
1558    to immediate-fy a Converse message, set the most significant bit to 1
1559    in the Converse handler (x|0x8000). 
1560 */
1561 #if CMK_IMMEDIATE_MSG
1562 void CmiDelayImmediate();
1563 #  define CmiBecomeImmediate(msg) do { \
1564         CmiSetHandler(msg, (CmiGetHandler(msg))|0x8000); \
1565      } while (0)
1566 #  define CmiIsImmediate(msg)      ((CmiGetHandler(msg)) & 0x8000) 
1567 #  define CmiImmediateHandler(msg) ((CmiGetHandler(msg)) ^ 0x8000)
1568 /*
1569 #  define CmiIsImmediate(msg)   ((CmiGetHandler(msg) == CpvAccessOther(CmiImmediateMsgHandlerIdx,0)))
1570 #  define CmiBecomeImmediate(msg) do {\
1571         CmiSetXHandler(msg,CmiGetHandler(msg)); \
1572         CmiSetHandler(msg,CpvAccessOther(CmiImmediateMsgHandlerIdx,0)); \
1573      } while (0)
1574 #  define CmiImemdiateHandler(msg) (CmiGetXHandler(msg))
1575 */
1576 /* 
1577   for non smp and non intr based version, it returns _immRunning
1578   for smp, this doesnot matter - CkMyPe() comparasion normaly fails and
1579            non threadsafe CqsEnqueueGeneral is avoided.
1580 */
1581 #if CMK_NET_VERSION && ! CMK_SMP && ! defined(CMK_CPV_IS_SMP)
1582 extern int _immRunning;
1583 #  define CmiImmIsRunning()        (_immRunning)
1584 #else
1585 #  define CmiImmIsRunning()        (0)
1586 #endif
1587
1588 #else
1589 #  define CmiBecomeImmediate(msg) /* empty */
1590 #  define CmiIsImmediate(msg)   (0)
1591 #  define CmiImmIsRunning()       (0)
1592 #endif
1593
1594 /******** Memory Fence ********/
1595
1596 #if  CMK_SMP
1597 #if CMK_GCC_X86_ASM
1598 #define CmiMemoryReadFence()               __asm__ __volatile__("lfence" ::: "memory")
1599 #define CmiMemoryWriteFence()              __asm__ __volatile__("sfence" ::: "memory")
1600 #if 1
1601 #define CmiMemoryAtomicIncrement(someInt)  __asm__ __volatile__("lock incl (%0)" :: "r" (&(someInt)))
1602 #define CmiMemoryAtomicDecrement(someInt)  __asm__ __volatile__("lock decl (%0)" :: "r" (&(someInt)))
1603 #else
1604 /* this might be slightly faster, but does not compile with -O3 on net-darwin-x86_64 */
1605 #define CmiMemoryAtomicIncrement(someInt)  __asm__ __volatile__("lock incl %0" :: "m" (someInt))
1606 #define CmiMemoryAtomicDecrement(someInt)  __asm__ __volatile__("lock decl %0" :: "m" (someInt))
1607 #endif
1608 #define CmiMemoryAtomicFetchAndInc(input,output) __asm__ __volatile__( \
1609         "movl $1, %1\n\t" \
1610         "lock xaddl %1, %0" \
1611         : "=m"(input), "=r"(output) : "m"(input) : "memory")
1612 #elif CMK_GCC_IA64_ASM
1613 #define CmiMemoryReadFence()               __asm__ __volatile__("mf" ::: "memory")
1614 #define CmiMemoryWriteFence()              __asm__ __volatile__("mf" ::: "memory")
1615 #define CmiMemoryAtomicIncrement(someInt)  { int someInt_private; \
1616   __asm__ __volatile__("fetchadd4.rel %0=[%1],1": "=r" (someInt_private): "r"(&someInt) :"memory") }
1617 #define CmiMemoryAtomicDecrement(someInt)  { int someInt_private; \
1618   __asm__ __volatile__("fetchadd4.rel %0=[%1],-1": "=r" (someInt_private): "r"(&someInt) :"memory") }
1619 #define CmiMemoryAtomicFetchAndInc(input,output) __asm__ __volatile__("fetchadd4.rel %0=[%1],1": "=r" (output): "r"(&input) :"memory")
1620 #elif CMK_PPC_ASM
1621 #define CmiMemoryReadFence()               __asm__ __volatile__("eieio":::"memory")
1622 #define CmiMemoryWriteFence()              __asm__ __volatile__("eieio":::"memory")
1623 #define STRINGIFY(x) #x
1624 #define TOSTRING(x) STRINGIFY(x)
1625 #define AT TOSTRING(__LINE__)
1626 #define CmiMemoryAtomicIncrement(someInt)   { int someInt_private; \
1627      __asm__ __volatile__ (      \
1628         "loop%=:\n\t"       /* repeat until this succeeds */    \
1629         "lwarx  %1,0,%2\n\t" /* reserve the operand */   \
1630         "addi   %1,%1,1\n\t" /* add incr to it */        \
1631         "stwcx. %1,0,%2\n\t" /* put the sum back, and release it */      \
1632         "bne- loop%="       /* start-over on failure */ \
1633         : "=m"(someInt), "=&r"(someInt_private)      \
1634         : "r" (&someInt), "m"(someInt)       \
1635         : "memory"  \
1636      ); }
1637 #define CmiMemoryAtomicDecrement(someInt)   { int someInt_private; \
1638      __asm__ __volatile__ (      \
1639         "loop%=:\n\t"       /* repeat until this succeeds */    \
1640         "lwarx  %1,0,%2\n\t" /* reserve the operand */   \
1641         "subi   %1,%1,1\n\t" /* add incr to it */        \
1642         "stwcx. %1,0,%2\n\t" /* put the sum back, and release it */      \
1643         "bne- loop%="       /* start-over on failure */ \
1644         : "=m"(someInt), "=&r"(someInt_private)      \
1645         : "r" (&someInt), "m"(someInt)       \
1646         : "memory"  \
1647      ); }
1648 #define CmiMemoryAtomicFetchAndInc(input,output) __asm__ __volatile__ ( \
1649         "loop%=:  lwarx %1, 0, %2\n\t" \
1650         "addi %1, %1, 1\n\t" \
1651         "stwcx. %1, 0, %2\n\t" \
1652         "bne- loop%=" \
1653         : "=m"(input), "=&r"(output) : "r"(&input), "m"(input) : "memory")
1654 #else
1655 #define CMK_NO_ASM_AVAILABLE    1
1656 extern CmiNodeLock cmiMemoryLock;
1657 #define CmiMemoryReadFence()               { CmiLock(cmiMemoryLock); CmiUnlock(cmiMemoryLock); }
1658 #define CmiMemoryWriteFence()              { CmiLock(cmiMemoryLock); CmiUnlock(cmiMemoryLock); }
1659 #define CmiMemoryAtomicIncrement(someInt)  { CmiLock(cmiMemoryLock); someInt=someInt+1; CmiUnlock(cmiMemoryLock); }
1660 #define CmiMemoryAtomicDecrement(someInt)  { CmiLock(cmiMemoryLock); someInt=someInt-1; CmiUnlock(cmiMemoryLock); }
1661 #define CmiMemoryAtomicFetchAndInc(input,output) { CmiLock(cmiMemoryLock); output=input; input=output+1; CmiUnlock(cmiMemoryLock); }
1662 #endif
1663 #else
1664 #define CmiMemoryReadFence()
1665 #define CmiMemoryWriteFence()
1666 #define CmiMemoryAtomicIncrement(someInt)  someInt=someInt+1
1667 #define CmiMemoryAtomicDecrement(someInt)  someInt=someInt-1
1668 #define CmiMemoryAtomicFetchAndInc(input,output) output=input; input=output+1;
1669 #endif
1670
1671 /******** Performance Counters ********/
1672 void CmiInitCounters();
1673 void CmiStartCounters(int events[], int numEvents);
1674 void CmiStopCounters(int events[], CMK_TYPEDEF_INT8 values[], int numEvents);
1675
1676 /******** Trace ********/
1677
1678 /* this is the type for thread ID, mainly used for projection. */
1679 #define OBJ_ID_SZ 4
1680 typedef struct _CmiObjId {
1681 int id[OBJ_ID_SZ];
1682   /* 
1683    * **CWL** Note: setting initial values to -1 does not seem to be done for 
1684    *               LDObjid. Potential consistency problems could arise. This
1685    *               will probably have to be dealt with later.
1686    */
1687 #ifdef __cplusplus
1688   _CmiObjId() { 
1689     for (int i=0; i<OBJ_ID_SZ; i++) {
1690       id[i] = -1;
1691     }
1692   }
1693   int isNull() {
1694     for (int i=0; i<OBJ_ID_SZ; i++) {
1695       if (id[i] != -1) return CmiFalse;
1696     }
1697     return CmiTrue;
1698   }
1699   CmiBool operator==(const struct _CmiObjId& objid) const {
1700     for (int i=0; i<OBJ_ID_SZ; i++) if (id[i] != objid.id[i]) return CmiFalse;
1701     return CmiTrue;
1702   }
1703 #endif
1704 } CmiObjId;
1705
1706 /* public interface for thread id acquisition */
1707 CmiObjId *CthGetThreadID(CthThread th);
1708 void CthSetThreadID(CthThread th, int a, int b, int c);
1709
1710 void CthTraceResume(CthThread t);
1711
1712 /*FAULT_EVAC */
1713 #if CMK_BLUEGENE_CHARM
1714 #define CmiNodeAlive(x) (1)
1715 #else
1716 CpvExtern(char *,_validProcessors);
1717 #define CmiNodeAlive(x)  (CpvAccess(_validProcessors)[x])
1718 #endif
1719
1720 int CmiEndianness();
1721
1722 #ifndef CMK_OPTIMIZE
1723 extern void setMemoryTypeChare(void*); /* for memory debugging */
1724 extern void setMemoryTypeMessage(void*); /* for memory debugging */
1725 #else
1726 #define setMemoryTypeChare(p) /* empty memory debugging method */
1727 #define setMemoryTypeMessage(p) /* empty memory debugging method */
1728 #endif
1729
1730 #include "conv-cpm.h"
1731 #include "conv-cpath.h"
1732 #include "conv-qd.h"
1733 #include "conv-random.h"
1734 #include "conv-lists.h"
1735 #include "conv-trace.h"
1736 #include "persistent.h"
1737 #if CMK_CELL
1738 #include "cell-api.h"
1739 #endif
1740 #ifdef __ONESIDED_IMPL
1741 #include "conv-onesided.h"
1742 #endif
1743
1744 /* The flag tells whether we are in the process of doing out-of-core emulation in BigSim */
1745 extern int BgOutOfCoreFlag;
1746 extern int BgInOutOfCoreMode;
1747
1748 #if defined(__cplusplus)
1749 }
1750 #endif
1751
1752 #if CMK_GRID_QUEUE_AVAILABLE
1753 #if defined(__cplusplus)
1754 extern "C" int CmiGetCluster (int pe);
1755 extern "C" int CmiGridQueueGetInterval ();
1756 extern "C" int CmiGridQueueGetThreshold ();
1757 extern "C" void CmiGridQueueRegister (int gid, int nInts, int index1, int index2, int index3);
1758 extern "C" void CmiGridQueueDeregister (int gid, int nInts, int index1, int index2, int index3);
1759 extern "C" void CmiGridQueueDeregisterAll ();
1760 extern "C" int CmiGridQueueLookup (int gid, int nInts, int index1, int index2, int index3);
1761 extern "C" int CmiGridQueueLookupMsg (char *msg);
1762 #else
1763 extern int CmiGetCluster (int pe);
1764 extern int CmiGridQueueGetInterval ();
1765 extern int CmiGridQueueGetThreshold ();
1766 extern void CmiGridQueueRegister (int gid, int nInts, int index1, int index2, int index3);
1767 extern void CmiGridQueueDeregister (int gid, int nInts, int index1, int index2, int index3);
1768 extern void CmiGridQueueDeregisterAll ();
1769 extern int CmiGridQueueLookup (int gid, int nInts, int index1, int index2, int index3);
1770 extern int CmiGridQueueLookupMsg (char *msg);
1771 #endif
1772 #endif
1773
1774 #include "debug-conv.h"
1775
1776 typedef struct {
1777   CmiUInt4 msgSize;
1778   CmiUInt2 senderPe;
1779   CmiUInt2 destination;
1780 } CmiFragmentHeader;
1781
1782
1783 #if CMK_HAS_LOG2
1784 #define CmiLog2  log2
1785 #else
1786 extern unsigned int CmiLog2(unsigned int);
1787 #endif
1788
1789 #endif /* CONVERSE_H */