3693f0d78c13e5bdffe27b66f614abec297b7f89
[charm.git] / src / conv-core / convcore.c
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 /** @defgroup Converse
9  * \brief Converse--a parallel portability layer.
10
11  * Converse is the lowest level inside the Charm++ hierarchy. It stands on top
12  * of the machine layer, and it provides all the common functionality across
13  * platforms.
14
15  * One converse program is running on every processor (or node in the smp
16  * version). it manages the message transmission, and the memory allocation.
17  * Charm++, which is on top of Converse, uses its functionality for
18  * interprocess *communication.
19
20  * In order to maintain multiple independent objects inside a single user space
21  * program, it uses a personalized version of threads, which can be executed,
22  * suspended, and migrated across processors.
23
24  * It provides a scheduler for message delivery: methods can be registered to
25  * the scheduler, and then messages allocated through CmiAlloc can be sent to
26  * the correspondent method in a remote processor. This is done through the
27  * converse header (which has few common fields, but is architecture dependent).
28 */
29
30 /** @file
31  * converse main core
32  * @ingroup Converse
33  */
34
35 /**
36  * @addtogroup Converse
37  * @{
38  */
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <errno.h>
44 #ifndef _WIN32
45 #include <sys/time.h>
46 #include <sys/resource.h>
47 #endif
48
49 #include "converse.h"
50 #include "conv-trace.h"
51 #include "sockRoutines.h"
52 #include "queueing.h"
53 #include "conv-ccs.h"
54 #include "ccs-server.h"
55 #include "memory-isomalloc.h"
56 #include "converseEvents.h"             /* projector */
57 #include "traceCoreCommon.h"    /* projector */
58 #include "machineEvents.h"     /* projector */
59
60 #if CMK_OUT_OF_CORE
61 #include "conv-ooc.h"
62 #endif
63
64 #if CONVERSE_POOL
65 #include "cmipool.h"
66 #endif
67
68 #if CMK_CONDS_USE_SPECIAL_CODE
69 CmiSwitchToPEFnPtr CmiSwitchToPE;
70 #endif
71
72 CpvExtern(int, _traceCoreOn);   /* projector */
73 extern void CcdModuleInit(char **);
74 extern void CmiMemoryInit(char **);
75 extern void CldModuleInit(char **);
76 extern void CmiInitCPUAffinity(char **);
77
78 #if CMK_WHEN_PROCESSOR_IDLE_USLEEP
79 #include <sys/types.h>
80 #include <sys/time.h>
81 #endif
82
83 #if CMK_TIMER_USE_TIMES
84 #include <sys/times.h>
85 #include <limits.h>
86 #include <unistd.h>
87 #endif
88
89 #if CMK_TIMER_USE_GETRUSAGE
90 #include <sys/time.h>
91 #include <sys/resource.h>
92 #endif
93
94 #if CMK_TIMER_USE_RDTSC
95 #include <string.h>
96 #include <unistd.h>
97 #include <time.h>
98 #include <stdio.h>
99 #include <sys/time.h>
100 #include <sys/resource.h>
101 #endif
102
103 #ifdef CMK_TIMER_USE_WIN32API
104 #include <stdlib.h>
105 #include <time.h>
106 #include <sys/types.h>
107 #include <sys/timeb.h>
108 #endif
109
110 #include "quiescence.h"
111
112 int cur_restart_phase = 1;      /* checkpointing/restarting phase counter */
113
114 static int CsdLocalMax = CSD_LOCAL_MAX_DEFAULT;
115
116 /*****************************************************************************
117  *
118  * Unix Stub Functions
119  *
120  ****************************************************************************/
121
122 #ifdef MEMMONITOR
123 typedef unsigned long mmulong;
124 CpvDeclare(mmulong,MemoryUsage);
125 CpvDeclare(mmulong,HiWaterMark);
126 CpvDeclare(mmulong,ReportedHiWaterMark);
127 CpvDeclare(int,AllocCount);
128 CpvDeclare(int,BlocksAllocated);
129 #endif
130
131 #define MAX_HANDLERS 512
132
133 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
134 CpvDeclare(int,expIOFlushFlag);
135 #if CMI_IO_BUFFER_EXPLICIT
136 /* 250k not too large depending on how slow terminal IO is */
137 #define DEFAULT_IO_BUFFER_SIZE 250000
138 CpvDeclare(char*,explicitIOBuffer);
139 CpvDeclare(int,expIOBufferSize);
140 #endif
141 #endif
142
143 #if CMK_NODE_QUEUE_AVAILABLE
144 void  *CmiGetNonLocalNodeQ();
145 #endif
146
147 CpvDeclare(void*, CsdSchedQueue);
148
149 #if CMK_OUT_OF_CORE
150 /* The Queue where the Prefetch Thread puts the messages from CsdSchedQueue  */
151 CpvDeclare(void*, CsdPrefetchQueue);
152 pthread_mutex_t prefetchLock;
153 #endif
154
155 #if CMK_NODE_QUEUE_AVAILABLE
156 CsvDeclare(void*, CsdNodeQueue);
157 CsvDeclare(CmiNodeLock, CsdNodeQueueLock);
158 #endif
159 CpvDeclare(int,   CsdStopFlag);
160 CpvDeclare(int,   CsdLocalCounter);
161
162 CmiNodeLock smp_mutex;               /* for smp */
163
164 #if CONVERSE_VERSION_VMI
165 void *CMI_VMI_CmiAlloc (int size);
166 void CMI_VMI_CmiFree (void *ptr);
167 #endif
168
169 #if CONVERSE_VERSION_ELAN
170 void* elan_CmiAlloc(int size);
171 #endif
172
173 #if CMK_USE_IBVERBS
174 void *infi_CmiAlloc(int size);
175 void infi_CmiFree(void *ptr);
176 #endif
177
178
179 #if CMK_GRID_QUEUE_AVAILABLE
180 CpvDeclare(void *, CkGridObject);
181 CpvDeclare(void *, CsdGridQueue);
182 #endif
183
184
185 /*****************************************************************************
186  *
187  * Command-Line Argument (CLA) parsing routines.
188  *
189  *****************************************************************************/
190
191 static int usageChecked=0; /* set when argv has been searched for a usage request */
192 static int printUsage=0; /* if set, print command-line usage information */
193 static const char *CLAformatString="%20s %10s %s\n";
194
195 /* This little list of CLA's holds the argument descriptions until it's
196    safe to print them--it's needed because the net- versions don't have 
197    printf until they're pretty well started.
198  */
199 typedef struct {
200         const char *arg; /* Flag name, like "-foo"*/
201         const char *param; /* Argument's parameter type, like "integer" or "none"*/
202         const char *desc; /* Human-readable description of what it does */
203 } CLA;
204 static int CLAlistLen=0;
205 static int CLAlistMax=0;
206 static CLA *CLAlist=NULL;
207
208 /* Add this CLA */
209 static void CmiAddCLA(const char *arg,const char *param,const char *desc) {
210         int i;
211         if (CmiMyPe()!=0) return; /*Don't bother if we're not PE 0*/
212         if (desc==NULL) return; /*It's an internal argument*/
213         if (usageChecked) { /* Printf should work now */
214                 if (printUsage)
215                         CmiPrintf(CLAformatString,arg,param,desc);
216         }
217         else { /* Printf doesn't work yet-- just add to the list.
218                 This assumes the const char *'s are static references,
219                 which is probably reasonable. */
220                 i=CLAlistLen++;
221                 if (CLAlistLen>CLAlistMax) { /*Grow the CLA list */
222                         CLAlistMax=16+2*CLAlistLen;
223                         CLAlist=realloc(CLAlist,sizeof(CLA)*CLAlistMax);\
224                 }
225                 CLAlist[i].arg=arg;
226                 CLAlist[i].param=param;
227                 CLAlist[i].desc=desc;
228         }
229 }
230
231 /* Print out the stored list of CLA's */
232 static void CmiPrintCLAs(void) {
233         int i;
234         if (CmiMyPe()!=0) return; /*Don't bother if we're not PE 0*/
235         CmiPrintf("Converse Machine Command-line Parameters:\n ");
236         CmiPrintf(CLAformatString,"Option:","Parameter:","Description:");
237         for (i=0;i<CLAlistLen;i++) {
238                 CLA *c=&CLAlist[i];
239                 CmiPrintf(CLAformatString,c->arg,c->param,c->desc);
240         }
241 }
242
243 /**
244  * Determines if command-line usage information should be printed--
245  * that is, if a "-?", "-h", or "--help" flag is present.
246  * Must be called after printf is setup.
247  */
248 void CmiArgInit(char **argv) {
249         int i;
250         for (i=0;argv[i]!=NULL;i++)
251         {
252                 if (0==strcmp(argv[i],"-?") ||
253                     0==strcmp(argv[i],"-h") ||
254                     0==strcmp(argv[i],"--help")) 
255                 {
256                         printUsage=1;
257                         /* Don't delete arg:  CmiDeleteArgs(&argv[i],1);
258                           Leave it there for user program to see... */
259                         CmiPrintCLAs();
260                 }
261         }
262         if (CmiMyPe()==0) { /* Throw away list of stored CLA's */
263                 CLAlistLen=CLAlistMax=0;
264                 free(CLAlist); CLAlist=NULL;
265         }
266         usageChecked=1;
267 }
268
269 /* Return 1 if we're currently printing command-line usage information. */
270 int CmiArgGivingUsage(void) {
271         return (CmiMyPe()==0) && printUsage;
272 }
273
274 /* Identifies the module that accepts the following command-line parameters */
275 void CmiArgGroup(const char *parentName,const char *groupName) {
276         if (CmiArgGivingUsage()) {
277                 if (groupName==NULL) groupName=parentName; /* Start of a new group */
278                 CmiPrintf("\n%s Command-line Parameters:\n",groupName);
279         }
280 }
281
282 /*Count the number of non-NULL arguments in list*/
283 int CmiGetArgc(char **argv)
284 {
285         int i=0,argc=0;
286         while (argv[i++]!=NULL)
287                 argc++;
288         return argc;
289 }
290
291 /*Return a new, heap-allocated copy of the argv array*/
292 char **CmiCopyArgs(char **argv)
293 {
294         int argc=CmiGetArgc(argv);
295         char **ret=(char **)malloc(sizeof(char *)*(argc+1));
296         int i;
297         for (i=0;i<=argc;i++)
298                 ret[i]=argv[i];
299         return ret;
300 }
301
302 /*Delete the first k argument from the given list, shifting
303 all other arguments down by k spaces.
304 e.g., argv=={"a","b","c","d",NULL}, k==3 modifies
305 argv={"d",NULL,"c","d",NULL}
306 */
307 void CmiDeleteArgs(char **argv,int k)
308 {
309         int i=0;
310         while ((argv[i]=argv[i+k])!=NULL)
311                 i++;
312 }
313
314 /*Find the given argment and string option in argv.
315 If the argument is present, set the string option and
316 delete both from argv.  If not present, return NULL.
317 e.g., arg=="-name" returns "bob" from
318 argv=={"a.out","foo","-name","bob","bar"},
319 and sets argv={"a.out","foo","bar"};
320 */
321 int CmiGetArgStringDesc(char **argv,const char *arg,char **optDest,const char *desc)
322 {
323         int i;
324         CmiAddCLA(arg,"string",desc);
325         for (i=0;argv[i]!=NULL;i++)
326                 if (0==strcmp(argv[i],arg))
327                 {/*We found the argument*/
328                         if (argv[i+1]==NULL) CmiAbort("Argument not complete!");
329                         *optDest=argv[i+1];
330                         CmiDeleteArgs(&argv[i],2);
331                         return 1;
332                 }
333         return 0;/*Didn't find the argument*/
334 }
335 int CmiGetArgString(char **argv,const char *arg,char **optDest) {
336         return CmiGetArgStringDesc(argv,arg,optDest,"");
337 }
338
339 /*Find the given argument and floating-point option in argv.
340 Remove it and return 1; or return 0.
341 */
342 int CmiGetArgDoubleDesc(char **argv,const char *arg,double *optDest,const char *desc) {
343         char *number=NULL;
344         CmiAddCLA(arg,"number",desc);
345         if (!CmiGetArgStringDesc(argv,arg,&number,NULL)) return 0;
346         if (1!=sscanf(number,"%lg",optDest)) return 0;
347         return 1;
348 }
349 int CmiGetArgDouble(char **argv,const char *arg,double *optDest) {
350         return CmiGetArgDoubleDesc(argv,arg,optDest,"");
351 }
352
353 /*Find the given argument and integer option in argv.
354 If the argument is present, parse and set the numeric option,
355 delete both from argv, and return 1. If not present, return 0.
356 e.g., arg=="-pack" matches argv=={...,"-pack","27",...},
357 argv=={...,"-pack0xf8",...}, and argv=={...,"-pack=0777",...};
358 but not argv=={...,"-packsize",...}.
359 */
360 int CmiGetArgIntDesc(char **argv,const char *arg,int *optDest,const char *desc)
361 {
362         int i;
363         int argLen=strlen(arg);
364         CmiAddCLA(arg,"integer",desc);
365         for (i=0;argv[i]!=NULL;i++)
366                 if (0==strncmp(argv[i],arg,argLen))
367                 {/*We *may* have found the argument*/
368                         const char *opt=NULL;
369                         int nDel=0;
370                         switch(argv[i][argLen]) {
371                         case 0: /* like "-p","27" */
372                                 opt=argv[i+1]; nDel=2; break;
373                         case '=': /* like "-p=27" */
374                                 opt=&argv[i][argLen+1]; nDel=1; break;
375                         case '-':case '+':
376                         case '0':case '1':case '2':case '3':case '4':
377                         case '5':case '6':case '7':case '8':case '9':
378                                 /* like "-p27" */
379                                 opt=&argv[i][argLen]; nDel=1; break;
380                         default:
381                                 continue; /*False alarm-- skip it*/
382                         }
383                         if (opt==NULL) continue; /*False alarm*/
384                         if (sscanf(opt,"%i",optDest)<1) {
385                         /*Bad command line argument-- die*/
386                                 fprintf(stderr,"Cannot parse %s option '%s' "
387                                         "as an integer.\n",arg,opt);
388                                 CmiAbort("Bad command-line argument\n");
389                         }
390                         CmiDeleteArgs(&argv[i],nDel);
391                         return 1;
392                 }
393         return 0;/*Didn't find the argument-- dest is unchanged*/       
394 }
395 int CmiGetArgInt(char **argv,const char *arg,int *optDest) {
396         return CmiGetArgIntDesc(argv,arg,optDest,"");
397 }
398
399 /*Find the given argument in argv.  If present, delete
400 it and return 1; if not present, return 0.
401 e.g., arg=="-foo" matches argv=={...,"-foo",...} but not
402 argv={...,"-foobar",...}.
403 */
404 int CmiGetArgFlagDesc(char **argv,const char *arg,const char *desc)
405 {
406         int i;
407         CmiAddCLA(arg,"",desc);
408         for (i=0;argv[i]!=NULL;i++)
409                 if (0==strcmp(argv[i],arg))
410                 {/*We found the argument*/
411                         CmiDeleteArgs(&argv[i],1);
412                         return 1;
413                 }
414         return 0;/*Didn't find the argument*/
415 }
416 int CmiGetArgFlag(char **argv,const char *arg) {
417         return CmiGetArgFlagDesc(argv,arg,"");
418 }
419
420
421 /*****************************************************************************
422  *
423  * Stack tracing routines.
424  *
425  *****************************************************************************/
426 #include "cmibacktrace.c"
427
428 /*
429 Convert "X(Y) Z" to "Y Z"-- remove text prior to first '(', and supress
430 the next parenthesis.  Operates in-place on the character data.
431 or Convert X(Y) to "Y" only, when trimname=1
432 */
433 static char *_implTrimParenthesis(char *str, int trimname) {
434   char *lParen=str, *ret=NULL, *rParen=NULL;
435   while (*lParen!='(') {
436     if (*lParen==0) return str; /* No left parenthesis at all. */
437     lParen++;
438   }
439   /* now *lParen=='(', so trim it*/
440   ret=lParen+1;
441   rParen=ret;
442   while (*rParen!=')') {
443     if (*rParen==0) return ret; /* No right parenthesis at all. */
444     rParen++;
445   }
446   /* now *rParen==')', so trim it*/
447   *rParen=trimname?0:' ';
448   return ret;  
449 }
450
451 /*
452 Return the text description of this trimmed routine name, if 
453 it's a system-generated routine where we should stop printing. 
454 This is probably overkill, but improves the appearance of callbacks.
455 */
456 static const char* _implGetBacktraceSys(const char *name) {
457   if (0==strncmp(name,"_call",5)) 
458   { /*it might be something we're interested in*/
459     if (0==strncmp(name,"_call_",6)) return "Call Entry Method";
460     if (0==strncmp(name,"_callthr_",9)) return "Call Threaded Entry Method";
461   }
462   if (0==strncmp(name,"CthResume",9)) return "Resumed thread";
463   if (0==strncmp(name,"qt_args",7)) return "Converse thread";
464   
465   return 0; /*ordinary user routine-- just print normally*/
466 }
467
468 /** Print out the names of these function pointers. */
469 void CmiBacktracePrint(void **retPtrs,int nLevels) {
470   if (nLevels>0) {
471     int i;
472     char **names=CmiBacktraceLookup(retPtrs,nLevels);
473     if (names==NULL) return;
474     CmiPrintf("[%d] Stack Traceback:\n", CmiMyPe());
475     for (i=0;i<nLevels;i++) {
476       if (names[i] == NULL) continue;
477       const char *trimmed=_implTrimParenthesis(names[i], 0);
478       const char *print=trimmed;
479       const char *sys=_implGetBacktraceSys(print);
480       if (sys) {
481           CmiPrintf("  [%d] Charm++ Runtime: %s (%s)\n",i,sys,print);
482           break; /*Stop when we hit Charm++ runtime.*/
483       } else {
484           CmiPrintf("  [%d] %s\n",i,print);
485       }
486     }
487     free(names);
488   }
489 }
490
491 /* Print (to stdout) the names of the functions that have been 
492    called up to this point. nSkip is the number of routines on the
493    top of the stack to *not* print out. */
494 void CmiPrintStackTrace(int nSkip) {
495 #if CMK_USE_BACKTRACE
496         int nLevels=max_stack;
497         void *stackPtrs[max_stack];
498         CmiBacktraceRecord(stackPtrs,1+nSkip,&nLevels);
499         CmiBacktracePrint(stackPtrs,nLevels);
500 #endif
501 }
502
503 int CmiIsFortranLibraryCall() {
504 #if CMK_USE_BACKTRACE
505   int ret = 0;
506   int nLevels=9;
507   void *stackPtrs[18];
508   CmiBacktraceRecord(stackPtrs,1,&nLevels);
509   if (nLevels>0) {
510     int i;
511     char **names=CmiBacktraceLookup(stackPtrs,nLevels);
512     if (names==NULL) return 0;
513     for (i=0;i<nLevels;i++) {
514       if (names[i] == NULL) continue;
515       const char *trimmed=_implTrimParenthesis(names[i], 1);
516       if (strncmp(trimmed, "for__", 5) == 0                /* ifort */
517           || strncmp(trimmed, "_xlf", 4) == 0               /* xlf90 */
518           || strncmp(trimmed, "_xlfBeginIO", 11) == 0 
519          )
520           {  /* CmiPrintf("[%d] NAME:%s\n", CmiMyPe(), trimmed); */
521              ret = 1; break; }
522     }
523     free(names);
524   }
525   return ret;
526 #else
527   return 0;
528 #endif
529 }
530
531 /*****************************************************************************
532  *
533  * Statistics: currently, the following statistics are not updated by converse.
534  *
535  *****************************************************************************/
536
537 CpvDeclare(int, CstatsMaxChareQueueLength);
538 CpvDeclare(int, CstatsMaxForChareQueueLength);
539 CpvDeclare(int, CstatsMaxFixedChareQueueLength);
540 CpvStaticDeclare(int, CstatPrintQueueStatsFlag);
541 CpvStaticDeclare(int, CstatPrintMemStatsFlag);
542
543 void CstatsInit(argv)
544 char **argv;
545 {
546
547 #ifdef MEMMONITOR
548   CpvInitialize(mmulong,MemoryUsage);
549   CpvAccess(MemoryUsage) = 0;
550   CpvInitialize(mmulong,HiWaterMark);
551   CpvAccess(HiWaterMark) = 0;
552   CpvInitialize(mmulong,ReportedHiWaterMark);
553   CpvAccess(ReportedHiWaterMark) = 0;
554   CpvInitialize(int,AllocCount);
555   CpvAccess(AllocCount) = 0;
556   CpvInitialize(int,BlocksAllocated);
557   CpvAccess(BlocksAllocated) = 0;
558 #endif
559
560   CpvInitialize(int, CstatsMaxChareQueueLength);
561   CpvInitialize(int, CstatsMaxForChareQueueLength);
562   CpvInitialize(int, CstatsMaxFixedChareQueueLength);
563   CpvInitialize(int, CstatPrintQueueStatsFlag);
564   CpvInitialize(int, CstatPrintMemStatsFlag);
565
566   CpvAccess(CstatsMaxChareQueueLength) = 0;
567   CpvAccess(CstatsMaxForChareQueueLength) = 0;
568   CpvAccess(CstatsMaxFixedChareQueueLength) = 0;
569   CpvAccess(CstatPrintQueueStatsFlag) = 0;
570   CpvAccess(CstatPrintMemStatsFlag) = 0;
571
572 #if 0
573   if (CmiGetArgFlagDesc(argv,"+mems", "Print memory statistics at shutdown"))
574     CpvAccess(CstatPrintMemStatsFlag)=1;
575   if (CmiGetArgFlagDesc(argv,"+qs", "Print queue statistics at shutdown"))
576     CpvAccess(CstatPrintQueueStatsFlag)=1;
577 #endif
578 }
579
580 int CstatMemory(i)
581 int i;
582 {
583   return 0;
584 }
585
586 int CstatPrintQueueStats()
587 {
588   return CpvAccess(CstatPrintQueueStatsFlag);
589 }
590
591 int CstatPrintMemStats()
592 {
593   return CpvAccess(CstatPrintMemStatsFlag);
594 }
595
596 /*****************************************************************************
597  *
598  * Cmi handler registration
599  *
600  *****************************************************************************/
601
602 CpvDeclare(CmiHandlerInfo*, CmiHandlerTable);
603 CpvStaticDeclare(int  , CmiHandlerCount);
604 CpvStaticDeclare(int  , CmiHandlerLocal);
605 CpvStaticDeclare(int  , CmiHandlerGlobal);
606 CpvDeclare(int,         CmiHandlerMax);
607
608 static void CmiExtendHandlerTable(int atLeastLen) {
609     int max = CpvAccess(CmiHandlerMax);
610     int newmax = (atLeastLen+(atLeastLen>>2)+32);
611     int bytes = max*sizeof(CmiHandlerInfo);
612     int newbytes = newmax*sizeof(CmiHandlerInfo);
613     CmiHandlerInfo *nu = (CmiHandlerInfo*)malloc(newbytes);
614     CmiHandlerInfo *tab = CpvAccess(CmiHandlerTable);
615     _MEMCHECK(nu);
616     memcpy(nu, tab, bytes);
617     memset(((char *)nu)+bytes, 0, (newbytes-bytes));
618     free(tab); tab=nu;
619     CpvAccess(CmiHandlerTable) = tab;
620     CpvAccess(CmiHandlerMax) = newmax;
621 }
622
623 void CmiNumberHandler(int n, CmiHandler h)
624 {
625   CmiHandlerInfo *tab;
626   if (n >= CpvAccess(CmiHandlerMax)) CmiExtendHandlerTable(n);
627   tab = CpvAccess(CmiHandlerTable);
628   tab[n].hdlr = (CmiHandlerEx)h; /* LIE!  This assumes extra pointer will be ignored!*/
629   tab[n].userPtr = 0;
630 }
631 void CmiNumberHandlerEx(int n, CmiHandlerEx h,void *userPtr) {
632   CmiHandlerInfo *tab;
633   if (n >= CpvAccess(CmiHandlerMax)) CmiExtendHandlerTable(n);
634   tab = CpvAccess(CmiHandlerTable);
635   tab[n].hdlr = h;
636   tab[n].userPtr=userPtr;
637 }
638
639 #if CMI_LOCAL_GLOBAL_AVAILABLE /*Leave room for local and global handlers*/
640 #  define DIST_BETWEEN_HANDLERS 3
641 #else /*No local or global handlers; ordinary handlers are back-to-back*/
642 #  define DIST_BETWEEN_HANDLERS 1
643 #endif
644
645 int CmiRegisterHandler(CmiHandler h)
646 {
647   int Count = CpvAccess(CmiHandlerCount);
648   CmiNumberHandler(Count, h);
649   CpvAccess(CmiHandlerCount) = Count+DIST_BETWEEN_HANDLERS;
650   return Count;
651 }
652 int CmiRegisterHandlerEx(CmiHandlerEx h,void *userPtr)
653 {
654   int Count = CpvAccess(CmiHandlerCount);
655   CmiNumberHandlerEx(Count, h, userPtr);
656   CpvAccess(CmiHandlerCount) = Count+DIST_BETWEEN_HANDLERS;
657   return Count;
658 }
659
660 #if CMI_LOCAL_GLOBAL_AVAILABLE
661 int CmiRegisterHandlerLocal(h)
662 CmiHandler h;
663 {
664   int Local = CpvAccess(CmiHandlerLocal);
665   CmiNumberHandler(Local, h);
666   CpvAccess(CmiHandlerLocal) = Local+3;
667   return Local;
668 }
669
670 int CmiRegisterHandlerGlobal(h)
671 CmiHandler h;
672 {
673   int Global = CpvAccess(CmiHandlerGlobal);
674   if (CmiMyPe()!=0) 
675     CmiError("CmiRegisterHandlerGlobal must only be called on PE 0.\n");
676   CmiNumberHandler(Global, h);
677   CpvAccess(CmiHandlerGlobal) = Global+3;
678   return Global;
679 }
680 #endif
681
682 static void _cmiZeroHandler(void *msg) {
683         CmiAbort("Converse zero handler executed-- was a message corrupted?\n");
684 }
685
686 static void CmiHandlerInit()
687 {
688   CpvInitialize(CmiHandlerInfo *, CmiHandlerTable);
689   CpvInitialize(int         , CmiHandlerCount);
690   CpvInitialize(int         , CmiHandlerLocal);
691   CpvInitialize(int         , CmiHandlerGlobal);
692   CpvInitialize(int         , CmiHandlerMax);
693   CpvAccess(CmiHandlerCount)  = 0;
694   CpvAccess(CmiHandlerLocal)  = 1;
695   CpvAccess(CmiHandlerGlobal) = 2;
696   CpvAccess(CmiHandlerMax) = 0; /* Table will be extended on the first registration*/
697   CpvAccess(CmiHandlerTable) = NULL;
698   CmiRegisterHandler((CmiHandler)_cmiZeroHandler);
699 }
700
701
702 /******************************************************************************
703  *
704  * CmiTimer
705  *
706  * Here are two possible implementations of CmiTimer.  Some machines don't
707  * select either, and define the timer in machine.c instead.
708  *
709  *****************************************************************************/
710
711 #if CMK_TIMER_USE_TIMES
712
713 CpvStaticDeclare(double, clocktick);
714 CpvStaticDeclare(int,inittime_wallclock);
715 CpvStaticDeclare(int,inittime_virtual);
716
717 int CmiTimerIsSynchronized()
718 {
719   return 0;
720 }
721
722 void CmiTimerInit()
723 {
724   struct tms temp;
725   CpvInitialize(double, clocktick);
726   CpvInitialize(int, inittime_wallclock);
727   CpvInitialize(int, inittime_virtual);
728   CpvAccess(inittime_wallclock) = times(&temp);
729   CpvAccess(inittime_virtual) = temp.tms_utime + temp.tms_stime;
730   CpvAccess(clocktick) = 1.0 / (sysconf(_SC_CLK_TCK));
731 }
732
733 double CmiWallTimer()
734 {
735   struct tms temp;
736   double currenttime;
737   int now;
738
739   now = times(&temp);
740   currenttime = (now - CpvAccess(inittime_wallclock)) * CpvAccess(clocktick);
741   return (currenttime);
742 }
743
744 double CmiCpuTimer()
745 {
746   struct tms temp;
747   double currenttime;
748   int now;
749
750   times(&temp);
751   now = temp.tms_stime + temp.tms_utime;
752   currenttime = (now - CpvAccess(inittime_virtual)) * CpvAccess(clocktick);
753   return (currenttime);
754 }
755
756 double CmiTimer()
757 {
758   return CmiCpuTimer();
759 }
760
761 #endif
762
763 #if CMK_TIMER_USE_GETRUSAGE
764
765 static double inittime_wallclock;
766 CpvStaticDeclare(double, inittime_virtual);
767
768 int CmiTimerIsSynchronized()
769 {
770   return 0;
771 }
772
773 void CmiTimerInit()
774 {
775   struct timeval tv;
776   struct rusage ru;
777   CpvInitialize(double, inittime_virtual);
778
779   /* try to synchronize calling barrier */
780   CmiBarrier();
781   CmiBarrier();
782   CmiBarrier();
783
784   gettimeofday(&tv,0);
785   inittime_wallclock = (tv.tv_sec * 1.0) + (tv.tv_usec*0.000001);
786   getrusage(0, &ru); 
787   CpvAccess(inittime_virtual) =
788     (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
789     (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
790
791   CmiBarrier();
792 /*  CmiBarrierZero(); */
793 }
794
795 double CmiCpuTimer()
796 {
797   struct rusage ru;
798   double currenttime;
799
800   getrusage(0, &ru);
801   currenttime =
802     (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
803     (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
804   return currenttime - CpvAccess(inittime_virtual);
805 }
806
807 static double lastT = -1.0;
808
809 double CmiWallTimer()
810 {
811   struct timeval tv;
812   double currenttime;
813
814   gettimeofday(&tv,0);
815   currenttime = (tv.tv_sec * 1.0) + (tv.tv_usec * 0.000001);
816 #ifndef CMK_OPTIMIZE
817   if (lastT > 0.0 && currenttime < lastT) {
818     currenttime = lastT;
819   }
820   lastT = currenttime;
821 #endif
822   return currenttime - inittime_wallclock;
823 }
824
825 double CmiTimer()
826 {
827   return CmiCpuTimer();
828 }
829
830 #endif
831
832 #if CMK_TIMER_USE_RDTSC
833
834 static double readMHz(void)
835 {
836   double x;
837   char str[1000];
838   char buf[100];
839   FILE *fp;
840   CmiLock(smp_mutex);
841   fp = fopen("/proc/cpuinfo", "r");
842   if (fp != NULL)
843   while(fgets(str, 1000, fp)!=0) {
844     if(sscanf(str, "cpu MHz%[^:]",buf)==1)
845     {
846       char *s = strchr(str, ':'); s=s+1;
847       sscanf(s, "%lf", &x);
848       fclose(fp);
849       CmiUnlock(smp_mutex);
850       return x;
851     }
852   }
853   CmiUnlock(smp_mutex);
854   CmiAbort("Cannot read CPU MHz from /proc/cpuinfo file.");
855   return 0.0;
856 }
857
858 double _cpu_speed_factor;
859 CpvStaticDeclare(double, inittime_virtual);
860 CpvStaticDeclare(double, inittime_walltime);
861
862 double  CmiStartTimer(void)
863 {
864   return CpvAccess(inittime_walltime);
865 }
866
867 void CmiTimerInit()
868 {
869   struct rusage ru;
870
871   CmiBarrier();
872   CmiBarrier();
873
874   _cpu_speed_factor = 1.0/(readMHz()*1.0e6); 
875   rdtsc(); rdtsc(); rdtsc(); rdtsc(); rdtsc();
876   CpvInitialize(double, inittime_walltime);
877   CpvAccess(inittime_walltime) = CmiWallTimer();
878   CpvInitialize(double, inittime_virtual);
879   getrusage(0, &ru); 
880   CpvAccess(inittime_virtual) =
881     (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
882     (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
883
884   CmiBarrierZero();
885 }
886
887 double CmiCpuTimer()
888 {
889   struct rusage ru;
890   double currenttime;
891
892   getrusage(0, &ru);
893   currenttime =
894     (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
895     (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
896   return currenttime - CpvAccess(inittime_virtual);
897 }
898
899 #endif
900
901 #if CMK_VERSION_BLUEGENE || CMK_BLUEGENEP
902 #include "dcopy.h"
903 #endif
904
905 #if CMK_TIMER_USE_BLUEGENEL
906
907 #include "rts.h"
908
909 #if 0 
910 #define SPRN_TBRL 0x10C  /* Time Base Read Lower Register (user & sup R/O) */
911 #define SPRN_TBRU 0x10D  /* Time Base Read Upper Register (user & sup R/O) */
912 #define SPRN_PIR  0x11E  /* CPU id */
913
914 static inline unsigned long long BGLTimebase(void)
915 {
916   unsigned volatile u1, u2, lo;
917   union
918   {
919     struct { unsigned hi, lo; } w;
920     unsigned long long d;
921   } result;
922                                                                                 
923   do {
924     asm volatile ("mfspr %0,%1" : "=r" (u1) : "i" (SPRN_TBRU));
925     asm volatile ("mfspr %0,%1" : "=r" (lo) : "i" (SPRN_TBRL));
926     asm volatile ("mfspr %0,%1" : "=r" (u2) : "i" (SPRN_TBRU));
927   } while (u1!=u2);
928                                                                                 
929   result.w.lo = lo;
930   result.w.hi = u2;
931   return result.d;
932 }
933 #endif
934
935 static unsigned long long inittime_wallclock = 0;
936 CpvStaticDeclare(double, clocktick);
937
938 int CmiTimerIsSynchronized()
939 {
940   return 0;
941 }
942
943 void CmiTimerInit()
944 {
945   BGLPersonality dst;
946   CpvInitialize(double, clocktick);
947   int size = sizeof(BGLPersonality);
948   rts_get_personality(&dst, size);
949   CpvAccess(clocktick) = 1.0 / dst.clockHz;
950
951   /* try to synchronize calling barrier */
952   CmiBarrier();
953   CmiBarrier();
954   CmiBarrier();
955
956   /* inittime_wallclock = rts_get_timebase(); */
957   inittime_wallclock = 0.0;    /* use bgl absolute time */
958 }
959
960 double CmiWallTimer()
961 {
962   unsigned long long currenttime;
963   currenttime = rts_get_timebase();
964   return CpvAccess(clocktick)*(currenttime-inittime_wallclock);
965 }
966
967 double CmiCpuTimer()
968 {
969   return CmiWallTimer();
970 }
971
972 double CmiTimer()
973 {
974   return CmiWallTimer();
975 }
976
977 #endif
978
979 #if CMK_TIMER_USE_BLUEGENEP  /* This module just compiles with GCC charm. */
980
981 void CmiTimerInit() {}
982
983 #if 0
984 #include "common/bgp_personality.h"
985 #include <spi/bgp_SPI.h>
986
987 #define SPRN_TBRL 0x10C  /* Time Base Read Lower Register (user & sup R/O) */
988 #define SPRN_TBRU 0x10D  /* Time Base Read Upper Register (user & sup R/O) */
989 #define SPRN_PIR  0x11E  /* CPU id */
990
991 static inline unsigned long long BGPTimebase(void)
992 {
993   unsigned volatile u1, u2, lo;
994   union
995   {
996     struct { unsigned hi, lo; } w;
997     unsigned long long d;
998   } result;
999                                                                          
1000   do {
1001     asm volatile ("mfspr %0,%1" : "=r" (u1) : "i" (SPRN_TBRU));
1002     asm volatile ("mfspr %0,%1" : "=r" (lo) : "i" (SPRN_TBRL));
1003     asm volatile ("mfspr %0,%1" : "=r" (u2) : "i" (SPRN_TBRU));
1004   } while (u1!=u2);
1005                                                                          
1006   result.w.lo = lo;
1007   result.w.hi = u2;
1008   return result.d;
1009 }
1010
1011 static unsigned long long inittime_wallclock = 0;
1012 CpvStaticDeclare(double, clocktick);
1013
1014 int CmiTimerIsSynchronized()
1015 {
1016   return 0;
1017 }
1018
1019 void CmiTimerInit()
1020 {
1021   _BGP_Personality_t dst;
1022   CpvInitialize(double, clocktick);
1023   int size = sizeof(_BGP_Personality_t);
1024   rts_get_personality(&dst, size);
1025
1026   CpvAccess(clocktick) = 1.0 / (dst.Kernel_Config.FreqMHz * 1e6);
1027
1028   /* try to synchronize calling barrier */
1029   CmiBarrier();
1030   CmiBarrier();
1031   CmiBarrier();
1032
1033   inittime_wallclock = BGPTimebase (); 
1034 }
1035
1036 double CmiWallTimer()
1037 {
1038   unsigned long long currenttime;
1039   currenttime = BGPTimebase();
1040   return CpvAccess(clocktick)*(currenttime-inittime_wallclock);
1041 }
1042 #endif
1043
1044 #include "dcmf.h"
1045
1046 double CmiWallTimer () {
1047   return DCMF_Timer();
1048 }
1049
1050 double CmiCpuTimer()
1051 {
1052   return CmiWallTimer();
1053 }
1054
1055 double CmiTimer()
1056 {
1057   return CmiWallTimer();
1058 }
1059
1060 #endif
1061
1062
1063 #if CMK_TIMER_USE_WIN32API
1064
1065 CpvStaticDeclare(double, inittime_wallclock);
1066 CpvStaticDeclare(double, inittime_virtual);
1067
1068 void CmiTimerInit()
1069 {
1070 #ifdef __CYGWIN__
1071         struct timeb tv;
1072 #else
1073         struct _timeb tv;
1074 #endif
1075         clock_t       ru;
1076
1077         CpvInitialize(double, inittime_wallclock);
1078         CpvInitialize(double, inittime_virtual);
1079         _ftime(&tv);
1080         CpvAccess(inittime_wallclock) = tv.time*1.0 + tv.millitm*0.001;
1081         ru = clock();
1082         CpvAccess(inittime_virtual) = ((double) ru)/CLOCKS_PER_SEC;
1083 }
1084
1085 double CmiCpuTimer()
1086 {
1087         clock_t ru;
1088         double currenttime;
1089
1090         ru = clock();
1091         currenttime = (double) ru/CLOCKS_PER_SEC;
1092
1093         return currenttime - CpvAccess(inittime_virtual);
1094 }
1095
1096 double CmiWallTimer()
1097 {
1098 #ifdef __CYGWIN__
1099         struct timeb tv;
1100 #else
1101         struct _timeb tv;
1102 #endif
1103         double currenttime;
1104
1105         _ftime(&tv);
1106         currenttime = tv.time*1.0 + tv.millitm*0.001;
1107
1108         return currenttime - CpvAccess(inittime_wallclock);
1109 }
1110         
1111
1112 double CmiTimer()
1113 {
1114         return CmiCpuTimer();
1115 }
1116
1117 #endif
1118
1119 #if CMK_TIMER_USE_RTC
1120
1121 #if __crayx1
1122  /* For _rtc() on Cray X1 */
1123 #include <intrinsics.h>
1124 #endif
1125
1126 static double clocktick;
1127 CpvStaticDeclare(long long, inittime_wallclock);
1128
1129 void CmiTimerInit()
1130 {
1131   CpvInitialize(long long, inittime_wallclock);
1132   CpvAccess(inittime_wallclock) = _rtc();
1133   clocktick = 1.0 / (double)(sysconf(_SC_SV2_USER_TIME_RATE));
1134 }
1135
1136 double CmiWallTimer()
1137 {
1138   long long now;
1139
1140   now = _rtc();
1141   return (clocktick * (now - CpvAccess(inittime_wallclock)));
1142 }
1143
1144 double CmiCpuTimer()
1145 {
1146   return CmiWallTimer();
1147 }
1148
1149 double CmiTimer()
1150 {
1151   return CmiCpuTimer();
1152 }
1153
1154 #endif
1155
1156 #ifndef CMK_USE_SPECIAL_MESSAGE_QUEUE_CHECK
1157 /** Return 1 if our outgoing message queue 
1158    for this node is longer than this many bytes. */
1159 int CmiLongSendQueue(int forNode,int longerThanBytes) {
1160   return 0;
1161 }
1162 #endif
1163
1164 #if CMK_SIGNAL_USE_SIGACTION
1165 #include <signal.h>
1166 void CmiSignal(sig1, sig2, sig3, handler)
1167 int sig1, sig2, sig3;
1168 void (*handler)();
1169 {
1170   struct sigaction in, out ;
1171   in.sa_handler = handler;
1172   sigemptyset(&in.sa_mask);
1173   if (sig1) sigaddset(&in.sa_mask, sig1);
1174   if (sig2) sigaddset(&in.sa_mask, sig2);
1175   if (sig3) sigaddset(&in.sa_mask, sig3);
1176   in.sa_flags = 0;
1177   if (sig1) if (sigaction(sig1, &in, &out)<0) exit(1);
1178   if (sig2) if (sigaction(sig2, &in, &out)<0) exit(1);
1179   if (sig3) if (sigaction(sig3, &in, &out)<0) exit(1);
1180 }
1181 #endif
1182
1183 #if CMK_SIGNAL_USE_SIGACTION_WITH_RESTART
1184 #include <signal.h>
1185 void CmiSignal(sig1, sig2, sig3, handler)
1186 int sig1, sig2, sig3;
1187 void (*handler)();
1188 {
1189   struct sigaction in, out ;
1190   in.sa_handler = handler;
1191   sigemptyset(&in.sa_mask);
1192   if (sig1) sigaddset(&in.sa_mask, sig1);
1193   if (sig2) sigaddset(&in.sa_mask, sig2);
1194   if (sig3) sigaddset(&in.sa_mask, sig3);
1195   in.sa_flags = SA_RESTART;
1196   if (sig1) if (sigaction(sig1, &in, &out)<0) exit(1);
1197   if (sig2) if (sigaction(sig2, &in, &out)<0) exit(1);
1198   if (sig3) if (sigaction(sig3, &in, &out)<0) exit(1);
1199 }
1200 #endif
1201
1202 /*****************************************************************************
1203  *
1204  * The following is the CsdScheduler function.  A common
1205  * implementation is provided below.  The machine layer can provide an
1206  * alternate implementation if it so desires.
1207  *
1208  * void CmiDeliversInit()
1209  *
1210  *      - CmiInit promises to call this before calling CmiDeliverMsgs
1211  *        or any of the other functions in this section.
1212  *
1213  * int CmiDeliverMsgs(int maxmsgs)
1214  *
1215  *      - CmiDeliverMsgs will retrieve up to maxmsgs that were transmitted
1216  *        with the Cmi, and will invoke their handlers.  It does not wait
1217  *        if no message is unavailable.  Instead, it returns the quantity
1218  *        (maxmsgs-delivered), where delivered is the number of messages it
1219  *        delivered.
1220  *
1221  * void CmiDeliverSpecificMsg(int handlerno)
1222  *
1223  *      - Waits for a message with the specified handler to show up, then
1224  *        invokes the message's handler.  Note that unlike CmiDeliverMsgs,
1225  *        This function _does_ wait.
1226  *
1227  * For this common implementation to work, the machine layer must provide the
1228  * following:
1229  *
1230  * void *CmiGetNonLocal()
1231  *
1232  *      - returns a message just retrieved from some other PE, not from
1233  *        local.  If no such message exists, returns 0.
1234  *
1235  * CpvExtern(CdsFifo, CmiLocalQueue);
1236  *
1237  *      - a FIFO queue containing all messages from the local processor.
1238  *
1239  *****************************************************************************/
1240
1241 void CsdBeginIdle(void)
1242 {
1243   CcdCallBacks();
1244   _LOG_E_PROC_IDLE();   /* projector */
1245   CcdRaiseCondition(CcdPROCESSOR_BEGIN_IDLE) ;
1246 }
1247
1248 void CsdStillIdle(void)
1249 {
1250   CcdRaiseCondition(CcdPROCESSOR_STILL_IDLE);
1251 }
1252
1253 void CsdEndIdle(void)
1254 {
1255   _LOG_E_PROC_BUSY();   /* projector */
1256   CcdRaiseCondition(CcdPROCESSOR_BEGIN_BUSY) ;
1257 }
1258
1259 #if CMK_MEM_CHECKPOINT
1260 #define MESSAGE_PHASE_CHECK     \
1261         {       \
1262           int phase = CmiGetRestartPhase(msg);  \
1263           if (phase < cur_restart_phase) {      \
1264             /*CmiPrintf("[%d] discard message of phase %d cur_restart_phase:%d handler:%d. \n", CmiMyPe(), phase, cur_restart_phase, handler);*/        \
1265             CmiFree(msg);       \
1266             return;     \
1267           }     \
1268         }
1269 #else
1270 #define MESSAGE_PHASE_CHECK
1271 #endif
1272
1273 extern int _exitHandlerIdx;
1274
1275 void CmiHandleMessage(void *msg)
1276 {
1277 /* this is wrong because it counts the Charm++ messages in sched queue
1278         CpvAccess(cQdState)->mProcessed++;
1279 */
1280         CmiHandlerInfo *h;
1281 #ifndef CMK_OPTIMIZE
1282         CmiUInt2 handler=CmiGetHandler(msg); /* Save handler for use after msg is gone */
1283         _LOG_E_HANDLER_BEGIN(handler); /* projector */
1284         /* setMemoryStatus(1) */ /* charmdebug */
1285 #endif
1286
1287 /*
1288         FAULT_EVAC
1289 */
1290 /*      if((!CpvAccess(_validProcessors)[CmiMyPe()]) && handler != _exitHandlerIdx){
1291                 return;
1292         }*/
1293         
1294         MESSAGE_PHASE_CHECK
1295
1296         h=&CmiGetHandlerInfo(msg);
1297         (h->hdlr)(msg,h->userPtr);
1298 #ifndef CMK_OPTIMIZE
1299         /* setMemoryStatus(0) /* /* charmdebug */
1300         _LOG_E_HANDLER_END(handler);    /* projector */
1301 #endif
1302 }
1303
1304 #if CMK_CMIDELIVERS_USE_COMMON_CODE
1305
1306 void CmiDeliversInit()
1307 {
1308 }
1309
1310 int CmiDeliverMsgs(int maxmsgs)
1311 {
1312   return CsdScheduler(maxmsgs);
1313 }
1314
1315 #if CMK_OBJECT_QUEUE_AVAILABLE
1316 CpvDeclare(void *, CsdObjQueue);
1317 #endif
1318
1319 void CsdSchedulerState_new(CsdSchedulerState_t *s)
1320 {
1321 #if CMK_OBJECT_QUEUE_AVAILABLE
1322         s->objQ=CpvAccess(CsdObjQueue);
1323 #endif
1324         s->localQ=CpvAccess(CmiLocalQueue);
1325         s->schedQ=CpvAccess(CsdSchedQueue);
1326         s->localCounter=&(CpvAccess(CsdLocalCounter));
1327 #if CMK_NODE_QUEUE_AVAILABLE
1328         s->nodeQ=CsvAccess(CsdNodeQueue);
1329         s->nodeLock=CsvAccess(CsdNodeQueueLock);
1330 #endif
1331 #if CMK_GRID_QUEUE_AVAILABLE
1332         s->gridQ=CpvAccess(CsdGridQueue);
1333 #endif
1334 }
1335
1336 void *CsdNextMessage(CsdSchedulerState_t *s) {
1337         void *msg;
1338         if((*(s->localCounter))-- >0)
1339           {
1340               /* This avoids a race condition with migration detected by megatest*/
1341               msg=CdsFifo_Dequeue(s->localQ);
1342               if (msg!=NULL)
1343                 {
1344                   CpvAccess(cQdState)->mProcessed++;
1345                   return msg;       
1346                 }
1347               CqsDequeue(s->schedQ,(void **)&msg);
1348               if (msg!=NULL) return msg;
1349           }
1350         
1351         *(s->localCounter)=CsdLocalMax;
1352         if ( NULL!=(msg=CmiGetNonLocal()) || 
1353              NULL!=(msg=CdsFifo_Dequeue(s->localQ)) ) {
1354             CpvAccess(cQdState)->mProcessed++;
1355             return msg;
1356         }
1357 #if CMK_GRID_QUEUE_AVAILABLE
1358         CqsDequeue (s->gridQ, (void **) &msg);
1359         if (msg != NULL) {
1360           return (msg);
1361         }
1362 #endif
1363 #if CMK_NODE_QUEUE_AVAILABLE
1364         if (NULL!=(msg=CmiGetNonLocalNodeQ())) return msg;
1365         if (!CqsEmpty(s->nodeQ)
1366          && !CqsPrioGT(CqsGetPriority(s->nodeQ),
1367                        CqsGetPriority(s->schedQ))) {
1368           CmiLock(s->nodeLock);
1369           CqsDequeue(s->nodeQ,(void **)&msg);
1370           CmiUnlock(s->nodeLock);
1371           if (msg!=NULL) return msg;
1372         }
1373 #endif
1374 #if CMK_OBJECT_QUEUE_AVAILABLE
1375         if (NULL!=(msg=CdsFifo_Dequeue(s->objQ))) {
1376           return msg;
1377         }
1378 #endif
1379         if(!CsdLocalMax) {
1380           CqsDequeue(s->schedQ,(void **)&msg);
1381           if (msg!=NULL) return msg;        
1382         }
1383
1384         return NULL;
1385 }
1386
1387 int CsdScheduler(int maxmsgs)
1388 {
1389         if (maxmsgs<0) CsdScheduleForever();    
1390         else if (maxmsgs==0)
1391                 CsdSchedulePoll();
1392         else /*(maxmsgs>0)*/ 
1393                 return CsdScheduleCount(maxmsgs);
1394         return 0;
1395 }
1396
1397 /*Declare the standard scheduler housekeeping*/
1398 #define SCHEDULE_TOP \
1399       void *msg;\
1400       int cycle = CpvAccess(CsdStopFlag); \
1401       CsdSchedulerState_t state;\
1402       CsdSchedulerState_new(&state);\
1403
1404 /*A message is available-- process it*/
1405 #define SCHEDULE_MESSAGE \
1406       CmiHandleMessage(msg);\
1407       if (CpvAccess(CsdStopFlag) != cycle) break;\
1408
1409 /*No message available-- go (or remain) idle*/
1410 #define SCHEDULE_IDLE \
1411       if (!isIdle) {isIdle=1;CsdBeginIdle();}\
1412       else CsdStillIdle();\
1413       if (CpvAccess(CsdStopFlag) != cycle) {\
1414         CsdEndIdle();\
1415         break;\
1416       }\
1417 /*
1418         EVAC
1419 */
1420 extern void CkClearAllArrayElements();
1421
1422
1423 extern void machine_OffloadAPIProgress();
1424
1425 void CsdScheduleForever(void)
1426 {
1427   #if CMK_CELL
1428     #define CMK_CELL_PROGRESS_FREQ  96  /* (MSG-Q Entries x1.5) */
1429     int progressCount = CMK_CELL_PROGRESS_FREQ;
1430   #endif
1431
1432   #ifdef CMK_CUDA
1433     #define CMK_CUDA_PROGRESS_FREQ 50
1434     int cudaProgressCount = CMK_CUDA_PROGRESS_FREQ;
1435   #endif
1436
1437   int isIdle=0;
1438   SCHEDULE_TOP
1439   while (1) {
1440     msg = CsdNextMessage(&state);
1441     if (msg) { /*A message is available-- process it*/
1442       if (isIdle) {isIdle=0;CsdEndIdle();}
1443       SCHEDULE_MESSAGE
1444
1445       #if CMK_CELL
1446         if (progressCount <= 0) {
1447           //OffloadAPIProgress();
1448           machine_OffloadAPIProgress();
1449           progressCount = CMK_CELL_PROGRESS_FREQ;
1450         }
1451         progressCount--;
1452       #endif
1453
1454       #ifdef CMK_CUDA
1455         if (cudaProgressCount == 0) {
1456           gpuProgressFn(); 
1457           cudaProgressCount = CMK_CUDA_PROGRESS_FREQ; 
1458         }
1459         cudaProgressCount--; 
1460       #endif
1461
1462     } else { /*No message available-- go (or remain) idle*/
1463       SCHEDULE_IDLE
1464
1465       #if CMK_CELL
1466         //OffloadAPIProgress();
1467         machine_OffloadAPIProgress();
1468         progressCount = CMK_CELL_PROGRESS_FREQ;
1469       #endif
1470
1471       #ifdef CMK_CUDA
1472         gpuProgressFn(); 
1473         cudaProgressCount = CMK_CUDA_PROGRESS_FREQ;
1474       #endif
1475
1476     }
1477     CsdPeriodic();
1478   }
1479 }
1480 int CsdScheduleCount(int maxmsgs)
1481 {
1482   int isIdle=0;
1483   SCHEDULE_TOP
1484   while (1) {
1485     msg = CsdNextMessage(&state);
1486     if (msg) { /*A message is available-- process it*/
1487       if (isIdle) {isIdle=0;CsdEndIdle();}
1488       maxmsgs--; 
1489       SCHEDULE_MESSAGE
1490       if (maxmsgs==0) break;
1491     } else { /*No message available-- go (or remain) idle*/
1492       SCHEDULE_IDLE
1493     }
1494     CsdPeriodic();
1495   }
1496   return maxmsgs;
1497 }
1498
1499 void CsdSchedulePoll(void)
1500 {
1501   SCHEDULE_TOP
1502   while (1)
1503   {
1504         CsdPeriodic();
1505         /*CmiMachineProgressImpl(); ??? */
1506         if (NULL!=(msg = CsdNextMessage(&state)))
1507         {
1508              SCHEDULE_MESSAGE 
1509         }
1510         else break;
1511   }
1512 }
1513
1514 void CmiDeliverSpecificMsg(handler)
1515 int handler;
1516 {
1517   int *msg; int side;
1518   void *localqueue = CpvAccess(CmiLocalQueue);
1519  
1520   side = 0;
1521   while (1) {
1522     CsdPeriodic();
1523     side ^= 1;
1524     if (side) msg = CmiGetNonLocal();
1525     else      msg = CdsFifo_Dequeue(localqueue);
1526     if (msg) {
1527       if (CmiGetHandler(msg)==handler) {
1528         CpvAccess(cQdState)->mProcessed++;
1529         CmiHandleMessage(msg);
1530         return;
1531       } else {
1532         CdsFifo_Enqueue(localqueue, msg);
1533       }
1534     }
1535   }
1536 }
1537  
1538 #endif /* CMK_CMIDELIVERS_USE_COMMON_CODE */
1539
1540 /***************************************************************************
1541  *
1542  * Standin Schedulers.
1543  *
1544  * We use the following strategy to make sure somebody's always running
1545  * the scheduler (CsdScheduler).  Initially, we assume the main thread
1546  * is responsible for this.  If the main thread blocks, we create a
1547  * "standin scheduler" thread to replace it.  If the standin scheduler
1548  * blocks, we create another standin scheduler to replace that one,
1549  * ad infinitum.  Collectively, the main thread and all the standin
1550  * schedulers are called "scheduling threads".
1551  *
1552  * Suppose the main thread is blocked waiting for data, and a standin
1553  * scheduler is running instead.  Suppose, then, that the data shows
1554  * up and the main thread is CthAwakened.  This causes a token to be
1555  * pushed into the queue.  When the standin pulls the token from the
1556  * queue and handles it, the standin goes to sleep, and control shifts
1557  * back to the main thread.  In this way, unnecessary standins are put
1558  * back to sleep.  These sleeping standins are stored on the
1559  * CthSleepingStandins list.
1560  *
1561  ***************************************************************************/
1562
1563 CpvStaticDeclare(CthThread, CthMainThread);
1564 CpvStaticDeclare(CthThread, CthSchedulingThread);
1565 CpvStaticDeclare(CthThread, CthSleepingStandins);
1566 CpvStaticDeclare(int      , CthResumeNormalThreadIdx);
1567 CpvStaticDeclare(int      , CthResumeSchedulingThreadIdx);
1568
1569
1570 void CthStandinCode()
1571 {
1572   while (1) CsdScheduler(0);
1573 }
1574
1575 /* this fix the function pointer for thread migration and pup */
1576 static CthThread CthSuspendNormalThread()
1577 {
1578   return CpvAccess(CthSchedulingThread);
1579 }
1580
1581 void CthEnqueueSchedulingThread(CthThreadToken *token, int, int, unsigned int*);
1582 CthThread CthSuspendSchedulingThread();
1583
1584 CthThread CthSuspendSchedulingThread()
1585 {
1586   CthThread succ = CpvAccess(CthSleepingStandins);
1587
1588   if (succ) {
1589     CpvAccess(CthSleepingStandins) = CthGetNext(succ);
1590   } else {
1591     succ = CthCreate(CthStandinCode, 0, 256000);
1592     CthSetStrategy(succ,
1593                    CthEnqueueSchedulingThread,
1594                    CthSuspendSchedulingThread);
1595   }
1596   
1597   CpvAccess(CthSchedulingThread) = succ;
1598   return succ;
1599 }
1600
1601 void CthResumeNormalThread(CthThreadToken* token)
1602 {
1603   CthThread t = token->thread;
1604   if(t == NULL){
1605     free(token);
1606     return;
1607   }
1608 #ifndef CMK_OPTIMIZE
1609 #if ! CMK_TRACE_IN_CHARM
1610   if(CpvAccess(traceOn))
1611     CthTraceResume(t);
1612 /*    if(CpvAccess(_traceCoreOn)) 
1613                 resumeTraceCore();*/
1614 #endif
1615 #endif
1616     
1617   CthResume(t);
1618 }
1619
1620 void CthResumeSchedulingThread(CthThreadToken  *token)
1621 {
1622   CthThread t = token->thread;
1623   CthThread me = CthSelf();
1624   if (me == CpvAccess(CthMainThread)) {
1625     CthEnqueueSchedulingThread(CthGetToken(me),CQS_QUEUEING_FIFO, 0, 0);
1626   } else {
1627     CthSetNext(me, CpvAccess(CthSleepingStandins));
1628     CpvAccess(CthSleepingStandins) = me;
1629   }
1630   CpvAccess(CthSchedulingThread) = t;
1631 #ifndef CMK_OPTIMIZE
1632 #if ! CMK_TRACE_IN_CHARM
1633   if(CpvAccess(traceOn))
1634     CthTraceResume(t);
1635 /*    if(CpvAccess(_traceCoreOn)) 
1636                 resumeTraceCore();*/
1637 #endif
1638 #endif
1639   CthResume(t);
1640 }
1641
1642 void CthEnqueueNormalThread(CthThreadToken* token, int s, 
1643                                    int pb,unsigned int *prio)
1644 {
1645   CmiSetHandler(token, CpvAccess(CthResumeNormalThreadIdx));
1646   CsdEnqueueGeneral(token, s, pb, prio);
1647 }
1648
1649 void CthEnqueueSchedulingThread(CthThreadToken* token, int s, 
1650                                        int pb,unsigned int *prio)
1651 {
1652   CmiSetHandler(token, CpvAccess(CthResumeSchedulingThreadIdx));
1653   CsdEnqueueGeneral(token, s, pb, prio);
1654 }
1655
1656 void CthSetStrategyDefault(CthThread t)
1657 {
1658   CthSetStrategy(t,
1659                  CthEnqueueNormalThread,
1660                  CthSuspendNormalThread);
1661 }
1662
1663 void CthSchedInit()
1664 {
1665   CpvInitialize(CthThread, CthMainThread);
1666   CpvInitialize(CthThread, CthSchedulingThread);
1667   CpvInitialize(CthThread, CthSleepingStandins);
1668   CpvInitialize(int      , CthResumeNormalThreadIdx);
1669   CpvInitialize(int      , CthResumeSchedulingThreadIdx);
1670
1671   CpvAccess(CthMainThread) = CthSelf();
1672   CpvAccess(CthSchedulingThread) = CthSelf();
1673   CpvAccess(CthSleepingStandins) = 0;
1674   CpvAccess(CthResumeNormalThreadIdx) =
1675     CmiRegisterHandler((CmiHandler)CthResumeNormalThread);
1676   CpvAccess(CthResumeSchedulingThreadIdx) =
1677     CmiRegisterHandler((CmiHandler)CthResumeSchedulingThread);
1678   CthSetStrategy(CthSelf(),
1679                  CthEnqueueSchedulingThread,
1680                  CthSuspendSchedulingThread);
1681 }
1682
1683 void CsdInit(argv)
1684   char **argv;
1685 {
1686   CpvInitialize(void *, CsdSchedQueue);
1687   CpvInitialize(int,   CsdStopFlag);
1688   CpvInitialize(int,   CsdLocalCounter);
1689   if(!CmiGetArgIntDesc(argv,"+csdLocalMax",&CsdLocalMax,"Set the max number of local messages to process before forcing a check for remote messages."))
1690     {
1691       CsdLocalMax= CSD_LOCAL_MAX_DEFAULT;
1692     }
1693   CpvAccess(CsdLocalCounter) = CsdLocalMax;
1694   CpvAccess(CsdSchedQueue) = (void *)CqsCreate();
1695
1696 #if CMK_OBJECT_QUEUE_AVAILABLE
1697   CpvInitialize(void *,CsdObjQueue);
1698   CpvAccess(CsdObjQueue) = CdsFifo_Create();
1699 #endif
1700
1701 #if CMK_NODE_QUEUE_AVAILABLE
1702   CsvInitialize(CmiLock, CsdNodeQueueLock);
1703   CsvInitialize(void *, CsdNodeQueue);
1704   if (CmiMyRank() ==0) {
1705         CsvAccess(CsdNodeQueueLock) = CmiCreateLock();
1706         CsvAccess(CsdNodeQueue) = (void *)CqsCreate();
1707   }
1708   CmiNodeAllBarrier();
1709 #endif
1710
1711 #if CMK_GRID_QUEUE_AVAILABLE
1712   CsvInitialize(void *, CsdGridQueue);
1713   CpvAccess(CsdGridQueue) = (void *)CqsCreate();
1714 #endif
1715
1716   CpvAccess(CsdStopFlag)  = 0;
1717 }
1718
1719
1720 /*****************************************************************************
1721  *
1722  * Vector Send
1723  *
1724  * The last parameter "system" is by default at zero, in which case the normal
1725  * messages are sent. If it is set to 1, the CmiChunkHeader prepended to every
1726  * CmiAllocced message will also be sent (except for the first one). Useful for
1727  * AllToAll communication, and other system features. If system is 1, also all
1728  * the messages will be padded to 8 bytes. Thus, the caller must be aware of
1729  * that.
1730  *
1731  ****************************************************************************/
1732
1733 #if CMK_VECTOR_SEND_USES_COMMON_CODE
1734
1735 void CmiSyncVectorSend(int destPE, int n, int *sizes, char **msgs) {
1736   int total;
1737   char *mesg;
1738 #if CMK_USE_IBVERBS
1739   VECTOR_COMPACT(total, mesg, n, sizes, msgs,sizeof(infiCmiChunkHeader));
1740 #else
1741   VECTOR_COMPACT(total, mesg, n, sizes, msgs,sizeof(CmiChunkHeader));
1742 #endif  
1743   CmiSyncSendAndFree(destPE, total, mesg);
1744 }
1745
1746 CmiCommHandle CmiASyncVectorSend(int destPE, int n, int *sizes, char **msgs) {
1747   CmiSyncVectorSend(destPE, n, sizes, msgs);
1748   return NULL;
1749 }
1750
1751 void CmiSyncVectorSendAndFree(int destPE, int n, int *sizes, char **msgs) {
1752   int i;
1753   CmiSyncVectorSend(destPE, n, sizes, msgs);
1754   for(i=0;i<n;i++) CmiFree(msgs[i]);
1755   CmiFree(sizes);
1756   CmiFree(msgs);
1757 }
1758
1759 #endif
1760
1761 /*****************************************************************************
1762  *
1763  * Reduction management
1764  *
1765  * Only one reduction can be active at a single time in the program.
1766  * Moreover, since every call is supposed to pass in the same arguments,
1767  * having some static variables is not a problem for multithreading.
1768  * 
1769  * Except for "data" and "size", all the other parameters (which are all function
1770  * pointers) MUST be the same in every processor. Having different processors
1771  * pass in different function pointers results in an undefined behaviour.
1772  * 
1773  * The data passed in to CmiReduce and CmiNodeReduce is deleted by the system,
1774  * and MUST be allocated with CmiAlloc. The data passed in to the "Struct"
1775  * functions is deleted with the provided function, or it is left intact if no
1776  * function is specified.
1777  * 
1778  * The destination handler for the the first form MUST be embedded into the
1779  * message's header.
1780  * 
1781  * The pup function is used to pup the input data structure into a message to
1782  * be sent to the parent processor. This pup routine is currently used only
1783  * for sizing and packing, NOT unpacking. It MUST be non-null.
1784  * 
1785  * The merge function receives as first parameter the input "data", being it
1786  * a message or a complex data structure (it is up to the user to interpret it
1787  * correctly), and a list of incoming (packed) messages from the children.
1788  * The merge function is responsible to delete "data" if this is no longer needed.
1789  * The system will be in charge of deleting the messages passed in as the second
1790  * argument, and the return value of the function (using the provided deleteFn in
1791  * the second version, or CmiFree in the first). The merge function can return
1792  * data if the merge can be performed in-place. It MUST be non-null.
1793  * 
1794  * At the destination, on processor zero, the final data returned by the last
1795  * merge call will not be deleted by the system, and the CmiHandler function
1796  * will be in charge of its deletion.
1797  * 
1798  * CmiReduce/CmiReduceStruct MUST be called once by every processor,
1799  * CmiNodeReduce/CmiNodeReduceStruct MUST be called once by every node, and in
1800  * particular by the rank zero in each node.
1801  ****************************************************************************/
1802
1803 CpvStaticDeclare(int, CmiReductionMessageHandler);
1804 CpvStaticDeclare(int, _reduce_num_children);
1805 CpvStaticDeclare(int, _reduce_parent);
1806 CpvStaticDeclare(int, _reduce_received);
1807 CpvStaticDeclare(char**, _reduce_msg_list);
1808 CpvStaticDeclare(void*, _reduce_data);
1809 CpvStaticDeclare(int, _reduce_data_size);
1810 static CmiHandler _reduce_destination;
1811 static void * (*_reduce_mergeFn)(void*,void**,int);
1812 static void (*_reduce_pupFn)(void*,void*);
1813 static void (*_reduce_deleteFn)(void*);
1814
1815 CpvStaticDeclare(CmiUInt2, _reduce_seqID);
1816
1817 int CmiGetReductionHandler() { return CpvAccess(CmiReductionMessageHandler); }
1818 CmiHandler CmiGetReductionDestination() { return _reduce_destination; }
1819
1820 CmiReductionsInit() {
1821   CpvInitialize(int, CmiReductionMessageHandler);
1822   CpvAccess(CmiReductionMessageHandler) = CmiRegisterHandler((CmiHandler)CmiHandleReductionMessage);
1823   CpvInitialize(int, _reduce_num_children);
1824   CpvInitialize(int, _reduce_parent);
1825   CpvInitialize(int, _reduce_received);
1826   CpvInitialize(char**, _reduce_msg_list);
1827   CpvInitialize(void*, _reduce_data);
1828   CpvInitialize(int, _reduce_data_size);
1829   CpvAccess(_reduce_num_children) = 0;
1830   CpvAccess(_reduce_received) = 0;
1831   int numChildren = CmiNumSpanTreeChildren(CmiMyPe());
1832   if (numChildren > 0) {
1833     CpvAccess(_reduce_msg_list) = (char**)malloc(CmiNumSpanTreeChildren(CmiMyPe())*sizeof(void*));
1834   } else {
1835     CpvAccess(_reduce_msg_list) = NULL;
1836   }
1837
1838   CpvInitialize(CmiUInt2, _reduce_seqID);
1839   CpvAccess(_reduce_seqID) = 0x8000;
1840 }
1841
1842 int CmiReduceNextID() {
1843   if (CpvAccess(_reduce_seqID) == 0xffff) CpvAccess(_reduce_seqID) = 0x8000;
1844   return ++CpvAccess(_reduce_seqID);
1845 }
1846
1847 void CmiSendReduce() {
1848   void *mergedData = CpvAccess(_reduce_data);
1849   void *msg;
1850   int msg_size;
1851   if (CpvAccess(_reduce_num_children) > 0) {
1852     int i, offset=0;
1853     if (_reduce_pupFn != NULL) {
1854       offset = CmiMsgHeaderSizeBytes;
1855       for (i=0; i<CpvAccess(_reduce_num_children); ++i) CpvAccess(_reduce_msg_list)[i] += offset;
1856     }
1857     mergedData = _reduce_mergeFn(CpvAccess(_reduce_data), (void **)CpvAccess(_reduce_msg_list), CpvAccess(_reduce_num_children));
1858     for (i=0; i<CpvAccess(_reduce_num_children); ++i) CmiFree(CpvAccess(_reduce_msg_list)[i] - offset);
1859   }
1860   CpvAccess(_reduce_num_children) = 0;
1861   CpvAccess(_reduce_received) = 0;
1862   msg = mergedData;
1863   msg_size = CpvAccess(_reduce_data_size);
1864   if (CmiMyPe() != 0) {
1865     if (_reduce_pupFn != NULL) {
1866       pup_er p = pup_new_sizer();
1867       _reduce_pupFn(p, mergedData);
1868       msg_size = pup_size(p) + CmiMsgHeaderSizeBytes;
1869       pup_destroy(p);
1870       msg = CmiAlloc(msg_size);
1871       p = pup_new_toMem((void*)(((char*)msg)+CmiMsgHeaderSizeBytes));
1872       _reduce_pupFn(p, mergedData);
1873       pup_destroy(p);
1874       if (_reduce_deleteFn != NULL) _reduce_deleteFn(CpvAccess(_reduce_data));
1875     }
1876     CmiSetHandler(msg, CpvAccess(CmiReductionMessageHandler));
1877     /*CmiPrintf("CmiSendReduce(%d): sending %d bytes to %d\n",CmiMyPe(),msg_size,CpvAccess(_reduce_parent));*/
1878     CmiSyncSendAndFree(CpvAccess(_reduce_parent), msg_size, msg);
1879   } else {
1880     _reduce_destination(msg);
1881   }
1882 }
1883
1884 void CmiReduce(void *data, int size, void * (*mergeFn)(void*,void**,int)) {
1885   CpvAccess(_reduce_data) = data;
1886   CpvAccess(_reduce_data_size) = size;
1887   CpvAccess(_reduce_parent) = CmiSpanTreeParent(CmiMyPe());
1888   _reduce_destination = (CmiHandler)CmiGetHandlerFunction(data);
1889   _reduce_pupFn = NULL;
1890   _reduce_mergeFn = mergeFn;
1891   CpvAccess(_reduce_num_children) = CmiNumSpanTreeChildren(CmiMyPe());
1892   if (CpvAccess(_reduce_received) == CpvAccess(_reduce_num_children)) CmiSendReduce();
1893 }
1894
1895 void CmiReduceStruct(void *data, void (*pupFn)(void*,void*),
1896                      void * (*mergeFn)(void*,void**,int), CmiHandler dest,
1897                      void (*deleteFn)(void*)) {
1898   CpvAccess(_reduce_data) = data;
1899   CpvAccess(_reduce_parent) = CmiSpanTreeParent(CmiMyPe());
1900   _reduce_destination = dest;
1901   _reduce_pupFn = pupFn;
1902   _reduce_mergeFn = mergeFn;
1903   _reduce_deleteFn = deleteFn;
1904   CpvAccess(_reduce_num_children) = CmiNumSpanTreeChildren(CmiMyPe());
1905   if (CpvAccess(_reduce_received) == CpvAccess(_reduce_num_children)) CmiSendReduce();
1906   /*else CmiPrintf("CmiReduceStruct(%d): %d - %d\n",CmiMyPe(),CpvAccess(_reduce_received),CpvAccess(_reduce_num_children));*/
1907 }
1908
1909 void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int), int redID, int numChildren, int parent) {
1910   CmiAssert(CmiRankOf(CmiMyPe()) == 0);
1911   CpvAccess(_reduce_data) = data;
1912   CpvAccess(_reduce_data_size) = size;
1913   CpvAccess(_reduce_parent) = CmiNodeFirst(CmiNodeSpanTreeParent(CmiMyNode()));
1914   _reduce_destination = (CmiHandler)CmiGetHandlerFunction(data);
1915   _reduce_pupFn = NULL;
1916   _reduce_mergeFn = mergeFn;
1917   CpvAccess(_reduce_num_children) = CmiNumNodeSpanTreeChildren(CmiMyNode());
1918   if (CpvAccess(_reduce_received) == CpvAccess(_reduce_num_children)) CmiSendReduce();
1919 }
1920 /*
1921 //void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int), int redID) {
1922 //  CmiNodeReduce(data, size, mergeFn, redID, CmiNumNodeSpanTreeChildren(CmiMyNode()),
1923 //      CmiNodeFirst(CmiNodeSpanTreeParent(CmiMyNode())));
1924 //}
1925 //void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int), int numChildren, int parent) {
1926 //  CmiNodeReduce(data, size, mergeFn, CmiReduceNextID(), numChildren, parent);
1927 //}
1928 //void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int)) {
1929 //  CmiNodeReduce(data, size, mergeFn, CmiReduceNextID(), CmiNumNodeSpanTreeChildren(CmiMyNode()),
1930 //      CmiNodeFirst(CmiNodeSpanTreeParent(CmiMyNode())));
1931 //}
1932 */
1933
1934 void CmiNodeReduceStruct(void *data, void (*pupFn)(void*,void*),
1935                          void * (*mergeFn)(void*,void**,int), CmiHandler dest,
1936                          void (*deleteFn)(void*)) {
1937   CmiAssert(CmiRankOf(CmiMyPe()) == 0);
1938   CpvAccess(_reduce_data) = data;
1939   CpvAccess(_reduce_parent) = CmiNodeFirst(CmiNodeSpanTreeParent(CmiMyNode()));
1940   _reduce_destination = dest;
1941   _reduce_pupFn = pupFn;
1942   _reduce_mergeFn = mergeFn;
1943   _reduce_deleteFn = deleteFn;
1944   CpvAccess(_reduce_num_children) = CmiNumNodeSpanTreeChildren(CmiMyNode());
1945   if (CpvAccess(_reduce_received) == CpvAccess(_reduce_num_children)) CmiSendReduce();
1946 }
1947
1948 void CmiHandleReductionMessage(void *msg) {
1949   CpvAccess(_reduce_msg_list)[CpvAccess(_reduce_received)++] = msg;
1950   if (CpvAccess(_reduce_received) == CpvAccess(_reduce_num_children)) CmiSendReduce();
1951   /*else CmiPrintf("CmiHandleReductionMessage(%d): %d - %d\n",CmiMyPe(),CpvAccess(_reduce_received),CpvAccess(_reduce_num_children));*/
1952 }
1953
1954 /*****************************************************************************
1955  *
1956  * Multicast groups
1957  *
1958  ****************************************************************************/
1959
1960 #if CMK_MULTICAST_DEF_USE_COMMON_CODE
1961
1962 typedef struct GroupDef
1963 {
1964   union {
1965     char core[CmiMsgHeaderSizeBytes];
1966     struct GroupDef *next;
1967   } core;
1968   CmiGroup group;
1969   int npes;
1970   int pes[1];
1971 }
1972 *GroupDef;
1973
1974 #define GROUPTAB_SIZE 101
1975
1976 CpvStaticDeclare(int, CmiGroupHandlerIndex);
1977 CpvStaticDeclare(int, CmiGroupCounter);
1978 CpvStaticDeclare(GroupDef *, CmiGroupTable);
1979
1980 void CmiGroupHandler(GroupDef def)
1981 {
1982   /* receive group definition, insert into group table */
1983   GroupDef *table = CpvAccess(CmiGroupTable);
1984   unsigned int hashval, bucket;
1985   hashval = (def->group.id ^ def->group.pe);
1986   bucket = hashval % GROUPTAB_SIZE;
1987   def->core.next = table[bucket];
1988   table[bucket] = def;
1989 }
1990
1991 CmiGroup CmiEstablishGroup(int npes, int *pes)
1992 {
1993   /* build new group definition, broadcast it */
1994   CmiGroup grp; GroupDef def; int len, i;
1995   grp.id = CpvAccess(CmiGroupCounter)++;
1996   grp.pe = CmiMyPe();
1997   len = sizeof(struct GroupDef)+(npes*sizeof(int));
1998   def = (GroupDef)CmiAlloc(len);
1999   def->group = grp;
2000   def->npes = npes;
2001   for (i=0; i<npes; i++)
2002     def->pes[i] = pes[i];
2003   CmiSetHandler(def, CpvAccess(CmiGroupHandlerIndex));
2004   CmiSyncBroadcastAllAndFree(len, def);
2005   return grp;
2006 }
2007
2008 void CmiLookupGroup(CmiGroup grp, int *npes, int **pes)
2009 {
2010   unsigned int hashval, bucket;  GroupDef def;
2011   GroupDef *table = CpvAccess(CmiGroupTable);
2012   hashval = (grp.id ^ grp.pe);
2013   bucket = hashval % GROUPTAB_SIZE;
2014   for (def=table[bucket]; def; def=def->core.next) {
2015     if ((def->group.id == grp.id)&&(def->group.pe == grp.pe)) {
2016       *npes = def->npes;
2017       *pes = def->pes;
2018       return;
2019     }
2020   }
2021   *npes = 0; *pes = 0;
2022 }
2023
2024 void CmiGroupInit()
2025 {
2026   CpvInitialize(int, CmiGroupHandlerIndex);
2027   CpvInitialize(int, CmiGroupCounter);
2028   CpvInitialize(GroupDef *, CmiGroupTable);
2029   CpvAccess(CmiGroupHandlerIndex) = CmiRegisterHandler((CmiHandler)CmiGroupHandler);
2030   CpvAccess(CmiGroupCounter) = 0;
2031   CpvAccess(CmiGroupTable) =
2032     (GroupDef*)calloc(GROUPTAB_SIZE, sizeof(GroupDef));
2033   if (CpvAccess(CmiGroupTable) == 0)
2034     CmiAbort("Memory Allocation Error");
2035 }
2036
2037 #endif
2038
2039 /*****************************************************************************
2040  *
2041  * Common List-Cast and Multicast Code
2042  *
2043  ****************************************************************************/
2044
2045 #if CMK_MULTICAST_LIST_USE_COMMON_CODE
2046
2047 void CmiSyncListSendFn(int npes, int *pes, int len, char *msg)
2048 {
2049   int i;
2050   for(i=0;i<npes;i++) {
2051     CmiSyncSend(pes[i], len, msg);
2052   }
2053 }
2054
2055 CmiCommHandle CmiAsyncListSendFn(int npes, int *pes, int len, char *msg)
2056 {
2057   /* A better asynchronous implementation may be wanted, but at least it works */
2058   CmiSyncListSendFn(npes, pes, len, msg);
2059   return (CmiCommHandle) 0;
2060 }
2061
2062 void CmiFreeListSendFn(int npes, int *pes, int len, char *msg)
2063 {
2064   int i;
2065   for(i=0;i<npes-1;i++) {
2066     CmiSyncSend(pes[i], len, msg);
2067   }
2068   if (npes)
2069     CmiSyncSendAndFree(pes[npes-1], len, msg);
2070   else 
2071     CmiFree(msg);
2072 }
2073
2074 #endif
2075
2076 #if CMK_MULTICAST_GROUP_USE_COMMON_CODE
2077
2078 typedef struct MultiMsg
2079 {
2080   char core[CmiMsgHeaderSizeBytes];
2081   CmiGroup group;
2082   int pos;
2083   int origlen;
2084 }
2085 *MultiMsg;
2086
2087 CpvDeclare(int, CmiMulticastHandlerIndex);
2088
2089 void CmiMulticastDeliver(MultiMsg msg)
2090 {
2091   int npes, *pes; int olen, nlen, pos, child1, child2;
2092   olen = msg->origlen;
2093   nlen = olen + sizeof(struct MultiMsg);
2094   CmiLookupGroup(msg->group, &npes, &pes);
2095   if (pes==0) {
2096     CmiSyncSendAndFree(CmiMyPe(), nlen, msg);
2097     return;
2098   }
2099   if (npes==0) {
2100     CmiFree(msg);
2101     return;
2102   }
2103   if (msg->pos == -1) {
2104     msg->pos=0;
2105     CmiSyncSendAndFree(pes[0], nlen, msg);
2106     return;
2107   }
2108   pos = msg->pos;
2109   child1 = ((pos+1)<<1);
2110   child2 = child1-1;
2111   if (child1 < npes) {
2112     msg->pos = child1;
2113     CmiSyncSend(pes[child1], nlen, msg);
2114   }
2115   if (child2 < npes) {
2116     msg->pos = child2;
2117     CmiSyncSend(pes[child2], nlen, msg);
2118   }
2119   if(olen < sizeof(struct MultiMsg)) {
2120     memcpy(msg, msg+1, olen);
2121   } else {
2122     memcpy(msg, (((char*)msg)+olen), sizeof(struct MultiMsg));
2123   }
2124   CmiSyncSendAndFree(CmiMyPe(), olen, msg);
2125 }
2126
2127 void CmiMulticastHandler(MultiMsg msg)
2128 {
2129   CmiMulticastDeliver(msg);
2130 }
2131
2132 void CmiSyncMulticastFn(CmiGroup grp, int len, char *msg)
2133 {
2134   int newlen; MultiMsg newmsg;
2135   newlen = len + sizeof(struct MultiMsg);
2136   newmsg = (MultiMsg)CmiAlloc(newlen);
2137   if(len < sizeof(struct MultiMsg)) {
2138     memcpy(newmsg+1, msg, len);
2139   } else {
2140     memcpy(newmsg+1, msg+sizeof(struct MultiMsg), len-sizeof(struct MultiMsg));
2141     memcpy(((char *)newmsg+len), msg, sizeof(struct MultiMsg));
2142   }
2143   newmsg->group = grp;
2144   newmsg->origlen = len;
2145   newmsg->pos = -1;
2146   CmiSetHandler(newmsg, CpvAccess(CmiMulticastHandlerIndex));
2147   CmiMulticastDeliver(newmsg);
2148 }
2149
2150 void CmiFreeMulticastFn(CmiGroup grp, int len, char *msg)
2151 {
2152   CmiSyncMulticastFn(grp, len, msg);
2153   CmiFree(msg);
2154 }
2155
2156 CmiCommHandle CmiAsyncMulticastFn(CmiGroup grp, int len, char *msg)
2157 {
2158   CmiError("Async Multicast not implemented.");
2159   return (CmiCommHandle) 0;
2160 }
2161
2162 void CmiMulticastInit()
2163 {
2164   CpvInitialize(int, CmiMulticastHandlerIndex);
2165   CpvAccess(CmiMulticastHandlerIndex) =
2166     CmiRegisterHandler((CmiHandler)CmiMulticastHandler);
2167 }
2168
2169 #endif
2170
2171 /***************************************************************************
2172  *
2173  * Memory Allocation routines 
2174  *
2175  * A block of memory can consist of multiple chunks.  Each chunk has
2176  * a sizefield and a refcount.  The first chunk's refcount is a reference
2177  * count.  That's how many CmiFrees it takes to free the message.
2178  * Subsequent chunks have a refcount which is less than zero.  This is
2179  * the offset back to the start of the first chunk.
2180  *
2181  * Each chunk has a CmiChunkHeader before the user data, with the fields:
2182  *
2183  *  size: The user-allocated size of the chunk, in bytes.
2184  *
2185  *  ref: A magic reference count object. Ordinary blocks start with
2186  *     reference count 1.  When the reference count reaches zero,
2187  *     the block is deleted.  To support nested buffers, the 
2188  *     reference count can also be negative, which means it is 
2189  *     a byte offset to the enclosing buffer's reference count.
2190  *
2191  ***************************************************************************/
2192
2193
2194 void *CmiAlloc(int size)
2195 {
2196   char *res;
2197
2198 #if CONVERSE_VERSION_ELAN
2199   res = (char *) elan_CmiAlloc(size+sizeof(CmiChunkHeader));
2200 #elif CONVERSE_VERSION_VMI
2201   res = (char *) CMI_VMI_CmiAlloc(size+sizeof(CmiChunkHeader));
2202 #elif CMK_USE_IBVERBS
2203         res = (char *) infi_CmiAlloc(size+sizeof(CmiChunkHeader));
2204 #elif CONVERSE_POOL
2205   res =(char *) CmiPoolAlloc(size+sizeof(CmiChunkHeader));
2206 #else
2207   res =(char *) malloc_nomigrate(size+sizeof(CmiChunkHeader));
2208 #endif
2209
2210   _MEMCHECK(res);
2211
2212 #ifdef MEMMONITOR
2213   CpvAccess(MemoryUsage) += size+sizeof(CmiChunkHeader);
2214   CpvAccess(AllocCount)++;
2215   CpvAccess(BlocksAllocated)++;
2216   if (CpvAccess(MemoryUsage) > CpvAccess(HiWaterMark)) {
2217     CpvAccess(HiWaterMark) = CpvAccess(MemoryUsage);
2218   }
2219   if (CpvAccess(MemoryUsage) > 1.1 * CpvAccess(ReportedHiWaterMark)) {
2220     CmiPrintf("HIMEM STAT PE%d: %d Allocs, %d blocks, %lu K, Max %lu K\n",
2221             CmiMyPe(), CpvAccess(AllocCount), CpvAccess(BlocksAllocated),
2222             CpvAccess(MemoryUsage)/1024, CpvAccess(HiWaterMark)/1024);
2223     CpvAccess(ReportedHiWaterMark) = CpvAccess(MemoryUsage);
2224   }
2225   if ((CpvAccess(AllocCount) % 1000) == 0) {
2226     CmiPrintf("MEM STAT PE%d: %d Allocs, %d blocks, %lu K, Max %lu K\n",
2227             CmiMyPe(), CpvAccess(AllocCount), CpvAccess(BlocksAllocated),
2228             CpvAccess(MemoryUsage)/1024, CpvAccess(HiWaterMark)/1024);
2229   }
2230 #endif
2231
2232   res+=sizeof(CmiChunkHeader);
2233   SIZEFIELD(res)=size;
2234   REFFIELD(res)=1;
2235   return (void *)res;
2236 }
2237
2238 /** Follow the header links out to the most enclosing block */
2239 static void *CmiAllocFindEnclosing(void *blk) {
2240   int refCount = REFFIELD(blk);
2241   while (refCount < 0) {
2242     blk = (void *)((char*)blk+refCount); /* Jump to enclosing block */
2243     refCount = REFFIELD(blk);
2244   }
2245   return blk;
2246 }
2247
2248 /** Increment the reference count for this block's owner.
2249     This call must be matched by an equivalent CmiFree. */
2250 void CmiReference(void *blk)
2251 {
2252   REFFIELD(CmiAllocFindEnclosing(blk))++;
2253 }
2254
2255 /** Return the size of the user portion of this block. */
2256 int CmiSize(void *blk)
2257 {
2258   return SIZEFIELD(blk);
2259 }
2260
2261 /** Decrement the reference count for this block. */
2262 void CmiFree(void *blk)
2263 {
2264   void *parentBlk=CmiAllocFindEnclosing(blk);
2265   int refCount=REFFIELD(parentBlk);
2266 #ifndef CMK_OPTIMIZE
2267   if(refCount==0) /* Logic error: reference count shouldn't already have been zero */
2268     CmiAbort("CmiFree reference count was zero-- is this a duplicate free?");
2269 #endif
2270   refCount--;
2271   REFFIELD(parentBlk) = refCount;
2272   if(refCount==0) { /* This was the last reference to the block-- free it */
2273 #ifdef MEMMONITOR
2274     int size=SIZEFIELD(parentBlk);
2275     if (size > 1000000000) /* Absurdly large size field-- warning */
2276       CmiPrintf("MEMSTAT Uh-oh -- SIZEFIELD=%d\n",size);
2277     CpvAccess(MemoryUsage) -= (size + sizeof(CmiChunkHeader);
2278     CpvAccess(BlocksAllocated)--;
2279 #endif
2280
2281 #if CONVERSE_VERSION_ELAN
2282     elan_CmiFree(BLKSTART(parentBlk));
2283 #elif CONVERSE_VERSION_VMI
2284     CMI_VMI_CmiFree(BLKSTART(parentBlk));
2285 #elif CMK_USE_IBVERBS
2286                 infi_CmiFree(BLKSTART(parentBlk));
2287 #elif CONVERSE_POOL
2288     CmiPoolFree(BLKSTART(parentBlk));
2289 #else
2290     free_nomigrate(BLKSTART(parentBlk));
2291 #endif
2292   }
2293 }
2294
2295
2296 /***************************************************************************
2297  *
2298  * Temporary-memory Allocation routines 
2299  *
2300  *  This buffer augments the storage available on the regular machine stack
2301  * for fairly large temporary buffers, which allows us to use smaller machine
2302  * stacks.
2303  *
2304  ***************************************************************************/
2305
2306 #define CMI_TMP_BUF_MAX 128*1024 /* Allow this much temporary storage. */
2307
2308 typedef struct {
2309   char *buf; /* Start of temporary buffer */
2310   int cur; /* First unused location in temporary buffer */
2311   int max; /* Length of temporary buffer */
2312 } CmiTmpBuf_t;
2313 CpvDeclare(CmiTmpBuf_t,CmiTmpBuf); /* One temporary buffer per PE */
2314
2315 static void CmiTmpSetup(CmiTmpBuf_t *b) {
2316   b->buf=malloc(CMI_TMP_BUF_MAX);
2317   b->cur=0;
2318   b->max=CMI_TMP_BUF_MAX;
2319 }
2320
2321 void *CmiTmpAlloc(int size) {
2322   if (!CpvInitialized(CmiTmpBuf)) {
2323     return malloc(size);
2324   }
2325   else { /* regular case */
2326     CmiTmpBuf_t *b=&CpvAccess(CmiTmpBuf);
2327     void *t;
2328     if (b->cur+size>b->max) {
2329       if (b->max==0) /* We're just uninitialized */
2330         CmiTmpSetup(b);
2331       else /* We're really out of space! */
2332         CmiAbort("CmiTmpAlloc: asked for too much temporary buffer space");
2333     }
2334     t=b->buf+b->cur;
2335     b->cur+=size;
2336     return t;
2337   }
2338 }
2339 void CmiTmpFree(void *t) {
2340   if (!CpvInitialized(CmiTmpBuf)) {
2341     free(t);
2342   }
2343   else { /* regular case */
2344     CmiTmpBuf_t *b=&CpvAccess(CmiTmpBuf);
2345     /* t should point into our temporary buffer: figure out where */
2346     int cur=((const char *)t)-b->buf;
2347 #ifndef CMK_OPTIMIZE
2348     if (cur<0 || cur>b->max)
2349       CmiAbort("CmiTmpFree: called with an invalid pointer");
2350 #endif
2351     b->cur=cur;
2352   }
2353 }
2354
2355 void CmiTmpInit(char **argv) {
2356   CpvInitialize(CmiTmpBuf_t,CmiTmpBuf);
2357   /* Set up this processor's temporary buffer */
2358   CmiTmpSetup(&CpvAccess(CmiTmpBuf));
2359 }
2360
2361 /******************************************************************************
2362
2363   Cross-platform directory creation
2364
2365   ****************************************************************************/
2366 #ifdef _MSC_VER
2367 /* Windows directory creation: */
2368 #include <windows.h>
2369
2370 void CmiMkdir(const char *dirName) {
2371         CreateDirectory(dirName,NULL);
2372 }
2373
2374 #else /* !_MSC_VER */
2375 /* UNIX directory creation */
2376 #include <unistd.h> 
2377 #include <sys/stat.h> /* from "mkdir" man page */
2378 #include <sys/types.h>
2379
2380 void CmiMkdir(const char *dirName) {
2381         mkdir(dirName,0777);
2382 }
2383
2384 #endif
2385
2386
2387 /******************************************************************************
2388
2389   Multiple Send function                               
2390
2391   ****************************************************************************/
2392
2393 CpvDeclare(int, CmiMainHandlerIDP); /* Main handler that is run on every node */
2394
2395 /****************************************************************************
2396 * DESCRIPTION : This function call allows the user to send multiple messages
2397 *               from one processor to another, all intended for differnet 
2398 *               handlers.
2399 *
2400 *               Parameters :
2401 *
2402 *               destPE, len, int sizes[0..len-1], char *messages[0..len-1]
2403 *
2404 ****************************************************************************/
2405 /* Round up message size to the message granularity. 
2406    Does this by adding, then truncating.
2407 */
2408 static int roundUpSize(unsigned int s) {
2409   return (int)((s+sizeof(double)-1)&~(sizeof(double)-1));
2410 }
2411 /* Return the amount of message padding required for a message
2412    with this many user bytes. 
2413  */
2414 static int paddingSize(unsigned int s) {
2415   return roundUpSize(s)-s;
2416 }
2417
2418 /* Message header for a bundle of multiple-sent messages */
2419 typedef struct {
2420   char convHeader[CmiMsgHeaderSizeBytes];
2421   int nMessages; /* Number of distinct messages bundled below. */
2422   double pad; /* To align the first message, which follows this header */
2423 } CmiMultipleSendHeader;
2424
2425 static void _CmiMultipleSend(unsigned int destPE, int len, int sizes[], char *msgComps[], int immed)
2426 {
2427   CmiMultipleSendHeader header;
2428   int m; /* Outgoing message */
2429
2430 #if CMK_USE_IBVERBS
2431         infiCmiChunkHeader *msgHdr;
2432 #else
2433   CmiChunkHeader *msgHdr; /* Chunk headers for each message */
2434 #endif
2435         
2436   double pad = 0; /* padding required */
2437   int vecLen; /* Number of pieces in outgoing message vector */
2438   int *vecSizes; /* Sizes of each piece we're sending out. */
2439   char **vecPtrs; /* Pointers to each piece we're sending out. */
2440   int vec; /* Entry we're currently filling out in above array */
2441         
2442 #if CMK_USE_IBVERBS
2443   msgHdr = (infiCmiChunkHeader *)CmiTmpAlloc(len * sizeof(infiCmiChunkHeader));
2444 #else
2445   msgHdr = (CmiChunkHeader *)CmiTmpAlloc(len * sizeof(CmiChunkHeader));
2446 #endif
2447         
2448   /* Allocate memory for the outgoing vector*/
2449   vecLen=1+3*len; /* Header and 3 parts per message */
2450   vecSizes = (int *)CmiTmpAlloc(vecLen * sizeof(int));
2451   vecPtrs = (char **)CmiTmpAlloc(vecLen * sizeof(char *));
2452   vec=0;
2453   
2454   /* Build the header */
2455   header.nMessages=len;
2456   CmiSetHandler(&header, CpvAccess(CmiMainHandlerIDP));
2457 #if CMK_IMMEDIATE_MSG
2458   if (immed) CmiBecomeImmediate(&header);
2459 #endif
2460   vecSizes[vec]=sizeof(header); vecPtrs[vec]=(char *)&header;
2461   vec++;
2462
2463   /* Build an entry for each message: 
2464          | CmiChunkHeader | Message data | Message padding | ...next message entry ...
2465   */
2466   for (m=0;m<len;m++) {
2467 #if CMK_USE_IBVERBS
2468     msgHdr[m].chunkHeader.size=roundUpSize(sizes[m]); /* Size of message and padding */
2469     msgHdr[m].chunkHeader.ref=0; /* Reference count will be filled out on receive side */
2470 #else
2471     msgHdr[m].size=roundUpSize(sizes[m]); /* Size of message and padding */
2472     msgHdr[m].ref=0; /* Reference count will be filled out on receive side */
2473 #endif          
2474     
2475     /* First send the message's CmiChunkHeader (for use on receive side) */
2476 #if CMK_USE_IBVERBS
2477     vecSizes[vec]=sizeof(infiCmiChunkHeader);
2478 #else
2479     vecSizes[vec]=sizeof(CmiChunkHeader); 
2480 #endif          
2481                 vecPtrs[vec]=(char *)&msgHdr[m];
2482     vec++;
2483     
2484     /* Now send the actual message data */
2485     vecSizes[vec]=sizes[m]; vecPtrs[vec]=msgComps[m];
2486     vec++;
2487     
2488     /* Now send padding to align the next message on a double-boundary */
2489     vecSizes[vec]=paddingSize(sizes[m]); vecPtrs[vec]=(char *)&pad;
2490     vec++;
2491   }
2492   CmiAssert(vec==vecLen);
2493   
2494   CmiSyncVectorSend(destPE, vecLen, vecSizes, vecPtrs);
2495   
2496   CmiTmpFree(vecPtrs); /* CmiTmp: Be sure to throw away in opposite order of allocation */
2497   CmiTmpFree(vecSizes);
2498   CmiTmpFree(msgHdr);
2499 }
2500
2501 void CmiMultipleSend(unsigned int destPE, int len, int sizes[], char *msgComps[])
2502 {
2503   _CmiMultipleSend(destPE, len, sizes, msgComps, 0);
2504 }
2505
2506 void CmiMultipleIsend(unsigned int destPE, int len, int sizes[], char *msgComps[])
2507 {
2508   _CmiMultipleSend(destPE, len, sizes, msgComps, 1);
2509 }
2510
2511 /****************************************************************************
2512 * DESCRIPTION : This function initializes the main handler required for the
2513 *               CmiMultipleSend() function to work. 
2514 *               
2515 *               This function should be called once in any Converse program
2516 *               that uses CmiMultipleSend()
2517 *
2518 ****************************************************************************/
2519
2520 static void CmiMultiMsgHandler(char *msgWhole);
2521
2522 void CmiInitMultipleSend(void)
2523 {
2524   CpvInitialize(int,CmiMainHandlerIDP); 
2525   CpvAccess(CmiMainHandlerIDP) =
2526     CmiRegisterHandler((CmiHandler)CmiMultiMsgHandler);
2527 }
2528
2529 /****************************************************************************
2530 * DESCRIPTION : This function is the main handler that splits up the messages
2531 *               CmiMultipleSend() pastes together. 
2532 *
2533 ****************************************************************************/
2534
2535 static void CmiMultiMsgHandler(char *msgWhole)
2536 {
2537   int len=((CmiMultipleSendHeader *)msgWhole)->nMessages;
2538   int offset=sizeof(CmiMultipleSendHeader);
2539   int m;
2540   for (m=0;m<len;m++) {
2541 #if CMK_USE_IBVERBS
2542     infiCmiChunkHeader *ch=(infiCmiChunkHeader *)(msgWhole+offset);
2543     char *msg=(msgWhole+offset+sizeof(infiCmiChunkHeader));
2544     int msgSize=ch->chunkHeader.size; /* Size of user portion of message (plus padding at end) */
2545     ch->chunkHeader.ref=msgWhole-msg; 
2546                 ch->metaData =  registerMultiSendMesg(msg,msgSize);
2547 #else
2548     CmiChunkHeader *ch=(CmiChunkHeader *)(msgWhole+offset);
2549     char *msg=(msgWhole+offset+sizeof(CmiChunkHeader));
2550     int msgSize=ch->size; /* Size of user portion of message (plus padding at end) */
2551     ch->ref=msgWhole-msg; 
2552 #endif          
2553     /* Link new message to owner via a negative ref pointer */
2554     CmiReference(msg); /* Follows link & increases reference count of *msgWhole* */
2555     CmiSyncSendAndFree(CmiMyPe(), msgSize, msg);
2556 #if CMK_USE_IBVERBS
2557     offset+= sizeof(infiCmiChunkHeader) + msgSize;
2558 #else
2559     offset+= sizeof(CmiChunkHeader) + msgSize;
2560 #endif          
2561   }
2562   /* Release our reference to the whole message.  The message will
2563      only actually be deleted once all its sub-messages are free'd as well. */
2564   CmiFree(msgWhole);
2565 }
2566
2567 /****************************************************************************
2568 * Hypercube broadcast message passing.
2569 ****************************************************************************/
2570
2571 int HypercubeGetBcastDestinations(int mype, int total_pes, int k, int *dest_pes) {
2572   int num_pes = 0;
2573   for ( ; k>=0; --k) {
2574     /* add the processor destination at level k if it exist */
2575     dest_pes[num_pes] = mype ^ (1<<k);
2576     if (dest_pes[num_pes] >= total_pes) {
2577       /* find the first proc in the other part of the current dimention */
2578       dest_pes[num_pes] &= (-1)<<k;
2579       /* if the first proc there is over CmiNumPes() then there is no other
2580          dimension, otherwise if it is valid compute my correspondent in such
2581          a way to minimize the load for every processor */
2582       if (total_pes>dest_pes[num_pes]) dest_pes[num_pes] += (mype - (mype & ((-1)<<k))) % (total_pes - dest_pes[num_pes]);
2583       }
2584     if (dest_pes[num_pes] < total_pes) {
2585       /* if the destination is in the acceptable range increment num_pes */
2586       ++num_pes;
2587     }
2588   }
2589   return num_pes;
2590 }
2591
2592
2593 /****************************************************************************
2594 * DESCRIPTION : This function initializes the main handler required for the
2595 *               Immediate message
2596 *               
2597 *               This function should be called once in any Converse program
2598 *
2599 ****************************************************************************/
2600
2601 int _immediateLock = 0; /* if locked, all immediate message handling will be delayed. */
2602 int _immediateFlag = 0; /* if set, there is delayed immediate message. */
2603
2604 CpvDeclare(int, CmiImmediateMsgHandlerIdx); /* Main handler that is run on every node */
2605
2606 /* xdl is the real handler */
2607 static void CmiImmediateMsgHandler(char *msg)
2608 {
2609   CmiSetHandler(msg, CmiGetXHandler(msg));
2610   CmiHandleMessage(msg);
2611 }
2612
2613 void CmiInitImmediateMsg(void)
2614 {
2615   CpvInitialize(int,CmiImmediateMsgHandlerIdx); 
2616   CpvAccess(CmiImmediateMsgHandlerIdx) =
2617     CmiRegisterHandler((CmiHandler)CmiImmediateMsgHandler);
2618 }
2619
2620 /*#if !CMK_IMMEDIATE_MSG
2621 #if !CMK_MACHINE_PROGRESS_DEFINED
2622 void CmiProbeImmediateMsg()
2623 {
2624 }
2625 #endif
2626 #endif*/
2627
2628 /******** Idle timeout module (+idletimeout=30) *********/
2629
2630 typedef struct {
2631   int idle_timeout;/*Milliseconds to wait idle before aborting*/
2632   int is_idle;/*Boolean currently-idle flag*/
2633   int call_count;/*Number of timeout calls currently in flight*/
2634 } cmi_cpu_idlerec;
2635
2636 static void on_timeout(cmi_cpu_idlerec *rec,double curWallTime)
2637 {
2638   rec->call_count--;
2639   if(rec->call_count==0 && rec->is_idle==1) {
2640     CmiError("Idle time on PE %d exceeded specified timeout.\n", CmiMyPe());
2641     CmiAbort("Exiting.\n");
2642   }
2643 }
2644 static void on_idle(cmi_cpu_idlerec *rec,double curWallTime)
2645 {
2646   CcdCallFnAfter((CcdVoidFn)on_timeout, rec, rec->idle_timeout);
2647   rec->call_count++; /*Keeps track of overlapping timeout calls.*/  
2648   rec->is_idle = 1;
2649 }
2650 static void on_busy(cmi_cpu_idlerec *rec,double curWallTime)
2651 {
2652   rec->is_idle = 0;
2653 }
2654 static void CIdleTimeoutInit(char **argv)
2655 {
2656   int idle_timeout=0; /*Seconds to wait*/
2657   CmiGetArgIntDesc(argv,"+idle-timeout",&idle_timeout,"Abort if idle for this many seconds");
2658   if(idle_timeout != 0) {
2659     cmi_cpu_idlerec *rec=(cmi_cpu_idlerec *)malloc(sizeof(cmi_cpu_idlerec));
2660     _MEMCHECK(rec);
2661     rec->idle_timeout=idle_timeout*1000;
2662     rec->is_idle=0;
2663     rec->call_count=0;
2664     CcdCallOnCondition(CcdPROCESSOR_BEGIN_IDLE, (CcdVoidFn)on_idle, rec);
2665     CcdCallOnCondition(CcdPROCESSOR_BEGIN_BUSY, (CcdVoidFn)on_busy, rec);
2666   }
2667 }
2668
2669 /*****************************************************************************
2670  *
2671  * Converse Initialization
2672  *
2673  *****************************************************************************/
2674
2675 extern void CrnInit(void);
2676 extern void CmiIsomallocInit(char **argv);
2677 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
2678 void CmiIOInit(char **argv);
2679 #endif
2680
2681 static void CmiProcessPriority(char **argv)
2682 {
2683   int dummy, nicelevel=-100;      /* process priority */
2684   CmiGetArgIntDesc(argv,"+nice",&nicelevel,"Set the process priority level");
2685   /* ignore others */
2686   while (CmiGetArgIntDesc(argv,"+nice",&dummy,"Set the process priority level"));
2687   /* call setpriority once on each process to set process's priority */
2688   if (CmiMyRank() == 0 && nicelevel != -100)  {
2689 #ifndef _WIN32
2690     if (0!=setpriority(PRIO_PROCESS, 0, nicelevel))  {
2691       CmiPrintf("[%d] setpriority failed with value %d. \n", CmiMyPe(), nicelevel);
2692       perror("setpriority");
2693       CmiAbort("setpriority failed.");
2694     }
2695     else
2696       CmiPrintf("[%d] Charm++: setpriority %d\n", CmiMyPe(), nicelevel);
2697 #else
2698     HANDLE hProcess = GetCurrentProcess();
2699     DWORD dwPriorityClass = NORMAL_PRIORITY_CLASS;
2700     char *prio_str = "NORMAL_PRIORITY_CLASS";
2701     BOOL status;
2702     /*
2703        <-20:      real time
2704        -20--10:   high 
2705        -10-0:     above normal
2706        0:         normal
2707        0-10:      below normal
2708        10-:       idle
2709     */
2710     if (0) ;
2711 #ifdef BELOW_NORMAL_PRIORITY_CLASS
2712     else if (nicelevel<10 && nicelevel>0) {
2713       dwPriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
2714       prio_str = "BELOW_NORMAL_PRIORITY_CLASS";
2715     }
2716 #endif
2717     else if (nicelevel>0) {
2718       dwPriorityClass = IDLE_PRIORITY_CLASS;
2719       prio_str = "IDLE_PRIORITY_CLASS";
2720     }
2721     else if (nicelevel<=-20) {
2722       dwPriorityClass = REALTIME_PRIORITY_CLASS;
2723       prio_str = "REALTIME_PRIORITY_CLASS";
2724     }
2725 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
2726     else if (nicelevel>-10 && nicelevel<0) {
2727       dwPriorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
2728       prio_str = "ABOVE_NORMAL_PRIORITY_CLASS";
2729     }
2730 #endif
2731     else if (nicelevel<0) {
2732       dwPriorityClass = HIGH_PRIORITY_CLASS;
2733       prio_str = "HIGH_PRIORITY_CLASS";
2734     }
2735     status = SetPriorityClass(hProcess, dwPriorityClass);
2736     if (!status)  {
2737         int err=GetLastError();
2738         CmiPrintf("SetPriorityClass failed errno=%d, WSAerr=%d\n",errno, err);
2739         CmiAbort("SetPriorityClass failed.");
2740     }
2741     else
2742       CmiPrintf("[%d] Charm++: setpriority %s\n", CmiMyPe(), prio_str);
2743 #endif
2744   }
2745 }
2746
2747 void CommunicationServerInit()
2748 {
2749 #if CMK_IMMEDIATE_MSG
2750   CQdCpvInit();
2751   CpvInitialize(int,CmiImmediateMsgHandlerIdx); 
2752 #endif
2753 }
2754
2755 /**
2756   Main Converse initialization routine.  This routine is 
2757   called by the machine file (machine.c) to set up Converse.
2758   It's "Common" because it's shared by all the machine.c files. 
2759   
2760   The main task of this routine is to set up all the Cpv's
2761   (message queues, handler tables, etc.) used during main execution.
2762   
2763   On SMP versions, this initialization routine is called by 
2764   *all* processors of a node simultaniously.  It's *also* called
2765   by the communication thread, which is rather strange but needed
2766   for immediate messages.  Each call to this routine expects a 
2767   different copy of the argv arguments, so use CmiCopyArgs(argv).
2768   
2769   Requires:
2770     - A working network layer.
2771     - Working Cpv's and CmiNodeBarrier.
2772     - CthInit to already have been called.  CthInit is called
2773       from the machine layer directly, because some machine layers
2774       (like uth) use Converse threads internally.
2775
2776   Initialization is somewhat subtle, in that various modules
2777   won't work properly until they're initialized.  For example,
2778   nobody can register handlers before calling CmiHandlerInit.
2779 */
2780 void ConverseCommonInit(char **argv)
2781 {
2782   CmiArgInit(argv);
2783   CmiMemoryInit(argv);
2784 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
2785   CmiIOInit(argv);
2786 #endif
2787 #if CONVERSE_POOL
2788   CmiPoolAllocInit(30);  
2789 #endif
2790   CmiTmpInit(argv);
2791   CmiTimerInit();
2792   CstatsInit(argv);
2793
2794   CcdModuleInit(argv);
2795   CmiHandlerInit();
2796   CmiReductionsInit();
2797   CIdleTimeoutInit(argv);
2798   
2799 #if CMK_SHARED_VARS_POSIX_THREADS_SMP /*Used by the net-*-smp versions*/
2800   if(CmiMyRank() == 0){
2801         if(CmiGetArgFlagDesc(argv,"+CmiNoProcForComThread","Is there an extra processor for the communication thread on each node(only for net-smp-*) ?")){
2802                 _Cmi_noprocforcommthread=1;
2803         }
2804    }
2805 #endif
2806 #if CMK_MULTICORE
2807     _Cmi_noprocforcommthread = 1;
2808 #endif
2809         
2810 #ifndef CMK_OPTIMIZE
2811   traceInit(argv);
2812 /*initTraceCore(argv);*/ /* projector */
2813 #endif
2814   CmiProcessPriority(argv);
2815
2816 #if CMK_CCS_AVAILABLE
2817   CcsInit(argv);
2818 #endif
2819   CmiPersistentInit();
2820   CmiIsomallocInit(argv);
2821   CpdInit();
2822   CmiDeliversInit();
2823   CsdInit(argv);
2824   CthSchedInit();
2825   CmiGroupInit();
2826   CmiMulticastInit();
2827   CmiInitMultipleSend();
2828   CQdInit();
2829
2830   CrnInit();
2831   CmiInitImmediateMsg();
2832   CldModuleInit(argv);
2833   
2834 #if CMK_CELL
2835   void CmiInitCell();
2836   CmiInitCell();
2837 #endif
2838
2839 #ifdef CMK_CUDA
2840   initAPI(); 
2841 #endif
2842
2843   /* main thread is suspendable */
2844 /*
2845   CthSetSuspendable(CthSelf(), 0);
2846 */
2847
2848   CmiInitCPUAffinity(argv);
2849
2850 #if CMK_BLUEGENE_CHARM
2851    /* have to initialize QD here instead of _initCharm */
2852   extern void initQd();
2853   initQd();
2854 #endif
2855 }
2856
2857 void ConverseCommonExit(void)
2858 {
2859   CcsImpl_kill();
2860
2861 #ifndef CMK_OPTIMIZE
2862   traceClose();
2863 /*closeTraceCore();*/ /* projector */
2864 #endif
2865
2866 #if CMI_IO_BUFFER_EXPLICIT
2867   CmiFlush(stdout);  /* end of program, always flush */
2868 #endif
2869
2870 #if CMK_CELL
2871   CloseOffloadAPI();
2872 #endif
2873
2874 #if CMK_CUDA
2875   exitAPI(); 
2876 #endif
2877
2878 }
2879
2880
2881 #if CMK_CELL
2882
2883 void CmiInitCell()
2884 {
2885   // Create a unique string for each PPE to use for the timing
2886   //   data file's name
2887   char fileNameBuf[128];
2888   sprintf(fileNameBuf, "speTiming.%d", CmiMyPe());
2889
2890   InitOffloadAPI(offloadCallback, NULL, NULL, fileNameBuf);
2891   //CcdCallOnConditionKeep(CcdPERIODIC, 
2892   //      (CcdVoidFn) OffloadAPIProgress, NULL);
2893   CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,
2894       (CcdVoidFn) OffloadAPIProgress, NULL);
2895 }
2896
2897 #include "cell-api.c"
2898
2899 #endif
2900
2901 /****
2902  * CW Lee - 9/14/2005
2903  * Added a mechanism to allow some control over machines with extremely
2904  * inefficient terminal IO mechanisms. Case in point: the XT3 has a
2905  * 20ms flush overhead along with about 25MB/s bandwidth for IO. This,
2906  * coupled with a default setup using unbuffered stdout introduced
2907  * severe overheads (and hence limiting scaling) for applications like 
2908  * NAMD.
2909  */
2910 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
2911 void CmiIOInit(char **argv) {
2912   CpvInitialize(int, expIOFlushFlag);
2913 #if CMI_IO_BUFFER_EXPLICIT
2914   /* 
2915      Support for an explicit buffer only makes sense if the machine
2916      layer does not wish to make its own implementation.
2917
2918      Placing this after CmiMemoryInit() means that CmiMemoryInit()
2919      MUST NOT make use of stdout if an explicit buffer is requested.
2920
2921      The setvbuf function may only be used after opening a stream and
2922      before any other operations have been performed on it
2923   */
2924   CpvInitialize(char*, explicitIOBuffer);
2925   CpvInitialize(int, expIOBufferSize);
2926   if (!CmiGetArgIntDesc(argv,"+io_buffer_size", &CpvAccess(expIOBufferSize),
2927                         "Explicit IO Buffer Size")) {
2928     CpvAccess(expIOBufferSize) = DEFAULT_IO_BUFFER_SIZE;
2929   }
2930   if (CpvAccess(expIOBufferSize) <= 0) {
2931     CpvAccess(expIOBufferSize) = DEFAULT_IO_BUFFER_SIZE;
2932   }
2933   CpvAccess(explicitIOBuffer) = (char*)CmiAlloc(CpvAccess(expIOBufferSize)*
2934                                                 sizeof(char));
2935   if (setvbuf(stdout, CpvAccess(explicitIOBuffer), _IOFBF, 
2936               CpvAccess(expIOBufferSize))) {
2937     CmiAbort("Explicit IO Buffering failed\n");
2938   }
2939 #endif
2940 #if CMI_IO_FLUSH_USER
2941   /* system default to have user control flushing of IO */
2942   /* Now look for user override */
2943   CpvAccess(expIOFlushFlag) = !CmiGetArgFlagDesc(argv,"+io_flush_system",
2944                                                  "System Controls IO Flush");
2945 #else
2946   /* system default to have system handle IO flushing */
2947   /* Now look for user override */
2948   CpvAccess(expIOFlushFlag) = CmiGetArgFlagDesc(argv,"+io_flush_user",
2949                                                 "User Controls IO Flush");
2950 #endif
2951 }
2952 #endif
2953
2954 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
2955
2956 void CmiPrintf(const char *format, ...)
2957 {
2958   va_list args;
2959   va_start(args,format);
2960   vfprintf(stdout,format, args);
2961   if (CpvInitialized(expIOFlushFlag) && !CpvAccess(expIOFlushFlag)) {
2962     CmiFlush(stdout);
2963   }
2964   va_end(args);
2965 }
2966
2967 void CmiError(const char *format, ...)
2968 {
2969   va_list args;
2970   va_start(args,format);
2971   vfprintf(stderr,format, args);
2972   CmiFlush(stderr);  /* stderr is always flushed */
2973   va_end(args);
2974 }
2975
2976 #endif
2977
2978 void __cmi_assert(const char *expr, const char *file, int line)
2979 {
2980   CmiError("[%d] Assertion \"%s\" failed in file %s line %d.\n",
2981       CmiMyPe(), expr, file, line);
2982   CmiAbort("");
2983 }
2984
2985 char *CmiCopyMsg(char *msg, int len)
2986 {
2987   char *copy = (char *)CmiAlloc(len);
2988   _MEMCHECK(copy);
2989   memcpy(copy, msg, len);
2990   return copy;
2991 }
2992
2993 unsigned char computeCheckSum(unsigned char *data, int len)
2994 {
2995   int i;
2996   unsigned char ret = 0;
2997   for (i=0; i<len; i++) ret ^= (unsigned char)data[i];
2998   return ret;
2999 }
3000
3001 /*@}*/