modified the interface, added a new possibility of Cmi VectorSends to pack inside
[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
77 #if CMK_WHEN_PROCESSOR_IDLE_USLEEP
78 #include <sys/types.h>
79 #include <sys/time.h>
80 #endif
81
82 #if CMK_TIMER_USE_TIMES
83 #include <sys/times.h>
84 #include <limits.h>
85 #include <unistd.h>
86 #endif
87
88 #if CMK_TIMER_USE_GETRUSAGE
89 #include <sys/time.h>
90 #include <sys/resource.h>
91 #endif
92
93 #if CMK_TIMER_USE_RDTSC
94 #include <string.h>
95 #include <unistd.h>
96 #include <time.h>
97 #include <stdio.h>
98 #include <sys/time.h>
99 #include <sys/resource.h>
100 #endif
101
102 #ifdef CMK_TIMER_USE_WIN32API
103 #include <stdlib.h>
104 #include <time.h>
105 #include <sys/types.h>
106 #include <sys/timeb.h>
107 #endif
108
109 #include "quiescence.h"
110
111 int cur_restart_phase = 1;      /* checkpointing/restarting phase counter */
112
113 static int CsdLocalMax = CSD_LOCAL_MAX_DEFAULT;
114
115 /*****************************************************************************
116  *
117  * Unix Stub Functions
118  *
119  ****************************************************************************/
120
121 #ifdef MEMMONITOR
122 typedef unsigned long mmulong;
123 CpvDeclare(mmulong,MemoryUsage);
124 CpvDeclare(mmulong,HiWaterMark);
125 CpvDeclare(mmulong,ReportedHiWaterMark);
126 CpvDeclare(int,AllocCount);
127 CpvDeclare(int,BlocksAllocated);
128 #endif
129
130 #define MAX_HANDLERS 512
131
132 #if CMK_NODE_QUEUE_AVAILABLE
133 void  *CmiGetNonLocalNodeQ();
134 #endif
135
136 CpvDeclare(void*, CsdSchedQueue);
137
138 #if CMK_OUT_OF_CORE
139 /* The Queue where the Prefetch Thread puts the messages from CsdSchedQueue  */
140 CpvDeclare(void*, CsdPrefetchQueue);
141 pthread_mutex_t prefetchLock;
142 #endif
143
144 #if CMK_NODE_QUEUE_AVAILABLE
145 CsvDeclare(void*, CsdNodeQueue);
146 CsvDeclare(CmiNodeLock, CsdNodeQueueLock);
147 #endif
148 CpvDeclare(int,   CsdStopFlag);
149 CpvDeclare(int,   CsdLocalCounter);
150
151 #if CONVERSE_VERSION_VMI
152 void *CMI_VMI_CmiAlloc (int size);
153 void CMI_VMI_CmiFree (void *ptr);
154 #endif
155
156 /*****************************************************************************
157  *
158  * Command-Line Argument (CLA) parsing routines.
159  *
160  *****************************************************************************/
161
162 static int usageChecked=0; /* set when argv has been searched for a usage request */
163 static int printUsage=0; /* if set, print command-line usage information */
164 static const char *CLAformatString="%20s %10s %s\n";
165
166 /* This little list of CLA's holds the argument descriptions until it's
167    safe to print them--it's needed because the net- versions don't have 
168    printf until they're pretty well started.
169  */
170 typedef struct {
171         const char *arg; /* Flag name, like "-foo"*/
172         const char *param; /* Argument's parameter type, like "integer" or "none"*/
173         const char *desc; /* Human-readable description of what it does */
174 } CLA;
175 static int CLAlistLen=0;
176 static int CLAlistMax=0;
177 static CLA *CLAlist=NULL;
178
179 /* Add this CLA */
180 static void CmiAddCLA(const char *arg,const char *param,const char *desc) {
181         int i;
182         if (CmiMyPe()!=0) return; /*Don't bother if we're not PE 0*/
183         if (desc==NULL) return; /*It's an internal argument*/
184         if (usageChecked) { /* Printf should work now */
185                 if (printUsage)
186                         CmiPrintf(CLAformatString,arg,param,desc);
187         }
188         else { /* Printf doesn't work yet-- just add to the list.
189                 This assumes the const char *'s are static references,
190                 which is probably reasonable. */
191                 i=CLAlistLen++;
192                 if (CLAlistLen>CLAlistMax) { /*Grow the CLA list */
193                         CLAlistMax=16+2*CLAlistLen;
194                         CLAlist=realloc(CLAlist,sizeof(CLA)*CLAlistMax);\
195                 }
196                 CLAlist[i].arg=arg;
197                 CLAlist[i].param=param;
198                 CLAlist[i].desc=desc;
199         }
200 }
201
202 /* Print out the stored list of CLA's */
203 static void CmiPrintCLAs(void) {
204         int i;
205         if (CmiMyPe()!=0) return; /*Don't bother if we're not PE 0*/
206         CmiPrintf("Converse Machine Command-line Parameters:\n ");
207         CmiPrintf(CLAformatString,"Option:","Parameter:","Description:");
208         for (i=0;i<CLAlistLen;i++) {
209                 CLA *c=&CLAlist[i];
210                 CmiPrintf(CLAformatString,c->arg,c->param,c->desc);
211         }
212 }
213
214 /**
215  * Determines if command-line usage information should be printed--
216  * that is, if a "-?", "-h", or "--help" flag is present.
217  * Must be called after printf is setup.
218  */
219 void CmiArgInit(char **argv) {
220         int i;
221         for (i=0;argv[i]!=NULL;i++)
222         {
223                 if (0==strcmp(argv[i],"-?") ||
224                     0==strcmp(argv[i],"-h") ||
225                     0==strcmp(argv[i],"--help")) 
226                 {
227                         printUsage=1;
228                         /* Don't delete arg:  CmiDeleteArgs(&argv[i],1);
229                           Leave it there for user program to see... */
230                         CmiPrintCLAs();
231                 }
232         }
233         if (CmiMyPe()==0) { /* Throw away list of stored CLA's */
234                 CLAlistLen=CLAlistMax=0;
235                 free(CLAlist); CLAlist=NULL;
236         }
237         usageChecked=1;
238 }
239
240 /* Return 1 if we're currently printing command-line usage information. */
241 int CmiArgGivingUsage(void) {
242         return (CmiMyPe()==0) && printUsage;
243 }
244
245 /* Identifies the module that accepts the following command-line parameters */
246 void CmiArgGroup(const char *parentName,const char *groupName) {
247         if (CmiArgGivingUsage()) {
248                 if (groupName==NULL) groupName=parentName; /* Start of a new group */
249                 CmiPrintf("\n%s Command-line Parameters:\n",groupName);
250         }
251 }
252
253 /*Count the number of non-NULL arguments in list*/
254 int CmiGetArgc(char **argv)
255 {
256         int i=0,argc=0;
257         while (argv[i++]!=NULL)
258                 argc++;
259         return argc;
260 }
261
262 /*Return a new, heap-allocated copy of the argv array*/
263 char **CmiCopyArgs(char **argv)
264 {
265         int argc=CmiGetArgc(argv);
266         char **ret=(char **)malloc(sizeof(char *)*(argc+1));
267         int i;
268         for (i=0;i<=argc;i++)
269                 ret[i]=argv[i];
270         return ret;
271 }
272
273 /*Delete the first k argument from the given list, shifting
274 all other arguments down by k spaces.
275 e.g., argv=={"a","b","c","d",NULL}, k==3 modifies
276 argv={"d",NULL,"c","d",NULL}
277 */
278 void CmiDeleteArgs(char **argv,int k)
279 {
280         int i=0;
281         while ((argv[i]=argv[i+k])!=NULL)
282                 i++;
283 }
284
285 /*Find the given argment and string option in argv.
286 If the argument is present, set the string option and
287 delete both from argv.  If not present, return NULL.
288 e.g., arg=="-name" returns "bob" from
289 argv=={"a.out","foo","-name","bob","bar"},
290 and sets argv={"a.out","foo","bar"};
291 */
292 int CmiGetArgStringDesc(char **argv,const char *arg,char **optDest,const char *desc)
293 {
294         int i;
295         CmiAddCLA(arg,"string",desc);
296         for (i=0;argv[i]!=NULL;i++)
297                 if (0==strcmp(argv[i],arg))
298                 {/*We found the argument*/
299                         if (argv[i+1]==NULL) CmiAbort("Argument not complete!");
300                         *optDest=argv[i+1];
301                         CmiDeleteArgs(&argv[i],2);
302                         return 1;
303                 }
304         return 0;/*Didn't find the argument*/
305 }
306 int CmiGetArgString(char **argv,const char *arg,char **optDest) {
307         return CmiGetArgStringDesc(argv,arg,optDest,"");
308 }
309
310 /*Find the given argument and floating-point option in argv.
311 Remove it and return 1; or return 0.
312 */
313 int CmiGetArgDoubleDesc(char **argv,const char *arg,double *optDest,const char *desc) {
314         char *number=NULL;
315         CmiAddCLA(arg,"number",desc);
316         if (!CmiGetArgStringDesc(argv,arg,&number,NULL)) return 0;
317         if (1!=sscanf(number,"%lg",optDest)) return 0;
318         return 1;
319 }
320 int CmiGetArgDouble(char **argv,const char *arg,double *optDest) {
321         return CmiGetArgDoubleDesc(argv,arg,optDest,"");
322 }
323
324 /*Find the given argument and integer option in argv.
325 If the argument is present, parse and set the numeric option,
326 delete both from argv, and return 1. If not present, return 0.
327 e.g., arg=="-pack" matches argv=={...,"-pack","27",...},
328 argv=={...,"-pack0xf8",...}, and argv=={...,"-pack=0777",...};
329 but not argv=={...,"-packsize",...}.
330 */
331 int CmiGetArgIntDesc(char **argv,const char *arg,int *optDest,const char *desc)
332 {
333         int i;
334         int argLen=strlen(arg);
335         CmiAddCLA(arg,"integer",desc);
336         for (i=0;argv[i]!=NULL;i++)
337                 if (0==strncmp(argv[i],arg,argLen))
338                 {/*We *may* have found the argument*/
339                         const char *opt=NULL;
340                         int nDel=0;
341                         switch(argv[i][argLen]) {
342                         case 0: /* like "-p","27" */
343                                 opt=argv[i+1]; nDel=2; break;
344                         case '=': /* like "-p=27" */
345                                 opt=&argv[i][argLen+1]; nDel=1; break;
346                         case '-':case '+':
347                         case '0':case '1':case '2':case '3':case '4':
348                         case '5':case '6':case '7':case '8':case '9':
349                                 /* like "-p27" */
350                                 opt=&argv[i][argLen]; nDel=1; break;
351                         default:
352                                 continue; /*False alarm-- skip it*/
353                         }
354                         if (opt==NULL) continue; /*False alarm*/
355                         if (sscanf(opt,"%i",optDest)<1) {
356                         /*Bad command line argument-- die*/
357                                 fprintf(stderr,"Cannot parse %s option '%s' "
358                                         "as an integer.\n",arg,opt);
359                                 CmiAbort("Bad command-line argument\n");
360                         }
361                         CmiDeleteArgs(&argv[i],nDel);
362                         return 1;
363                 }
364         return 0;/*Didn't find the argument-- dest is unchanged*/       
365 }
366 int CmiGetArgInt(char **argv,const char *arg,int *optDest) {
367         return CmiGetArgIntDesc(argv,arg,optDest,"");
368 }
369
370 /*Find the given argument in argv.  If present, delete
371 it and return 1; if not present, return 0.
372 e.g., arg=="-foo" matches argv=={...,"-foo",...} but not
373 argv={...,"-foobar",...}.
374 */
375 int CmiGetArgFlagDesc(char **argv,const char *arg,const char *desc)
376 {
377         int i;
378         CmiAddCLA(arg,"",desc);
379         for (i=0;argv[i]!=NULL;i++)
380                 if (0==strcmp(argv[i],arg))
381                 {/*We found the argument*/
382                         CmiDeleteArgs(&argv[i],1);
383                         return 1;
384                 }
385         return 0;/*Didn't find the argument*/
386 }
387 int CmiGetArgFlag(char **argv,const char *arg) {
388         return CmiGetArgFlagDesc(argv,arg,"");
389 }
390
391
392 /*****************************************************************************
393  *
394  * Stack tracing routines.
395  *
396  *****************************************************************************/
397 #include "cmibacktrace.c"
398
399 /*
400 Convert "X(Y) Z" to "Y Z"-- remove text prior to first '(', and supress
401 the next parenthesis.  Operates in-place on the character data.
402 */
403 static char *_implTrimParenthesis(char *str) {
404   char *lParen=str, *ret=NULL, *rParen=NULL;
405   while (*lParen!='(') {
406     if (*lParen==0) return str; /* No left parenthesis at all. */
407     lParen++;
408   }
409   /* now *lParen=='(', so trim it*/
410   ret=lParen+1;
411   rParen=ret;
412   while (*rParen!=')') {
413     if (*rParen==0) return ret; /* No right parenthesis at all. */
414     rParen++;
415   }
416   /* now *rParen==')', so trim it*/
417   *rParen=' ';
418   return ret;  
419 }
420
421 /*
422 Return the text description of this trimmed routine name, if 
423 it's a system-generated routine where we should stop printing. 
424 This is probably overkill, but improves the appearance of callbacks.
425 */
426 static const char* _implGetBacktraceSys(const char *name) {
427   if (0==strncmp(name,"_call",5)) 
428   { /*it might be something we're interested in*/
429     if (0==strncmp(name,"_call_",6)) return "Call Entry Method";
430     if (0==strncmp(name,"_callthr_",9)) return "Call Threaded Entry Method";
431   }
432   if (0==strncmp(name,"CthResume",9)) return "Resumed thread";
433   if (0==strncmp(name,"qt_args",7)) return "Converse thread";
434   
435   return 0; /*ordinary user routine-- just print normally*/
436 }
437
438 /** Print out the names of these function pointers. */
439 void CmiBacktracePrint(void **retPtrs,int nLevels) {
440   if (nLevels>0) {
441     int i;
442     char **names=CmiBacktraceLookup(retPtrs,nLevels);
443     if (names==NULL) return;
444     CmiPrintf("Stack Traceback:\n");
445     for (i=0;i<nLevels;i++) {
446       const char *trimmed=_implTrimParenthesis(names[i]);
447       const char *print=trimmed;
448       const char *sys=_implGetBacktraceSys(print);
449       if (sys) {
450           CmiPrintf("  [%d] Charm++ Runtime: %s (%s)\n",i,sys,print);
451           break; /*Stop when we hit Charm++ runtime.*/
452       } else {
453           CmiPrintf("  [%d] %s\n",i,print);
454       }
455     }
456     free(names);
457   }
458 }
459
460 /* Print (to stdout) the names of the functions that have been 
461    called up to this point. nSkip is the number of routines on the
462    top of the stack to *not* print out. */
463 void CmiPrintStackTrace(int nSkip) {
464 #if CMK_USE_BACKTRACE
465         int nLevels=max_stack;
466         void *stackPtrs[max_stack];
467         CmiBacktraceRecord(stackPtrs,1+nSkip,&nLevels);
468         CmiBacktracePrint(stackPtrs,nLevels);
469 #endif
470 }
471
472 /*****************************************************************************
473  *
474  * Statistics: currently, the following statistics are not updated by converse.
475  *
476  *****************************************************************************/
477
478 CpvDeclare(int, CstatsMaxChareQueueLength);
479 CpvDeclare(int, CstatsMaxForChareQueueLength);
480 CpvDeclare(int, CstatsMaxFixedChareQueueLength);
481 CpvStaticDeclare(int, CstatPrintQueueStatsFlag);
482 CpvStaticDeclare(int, CstatPrintMemStatsFlag);
483
484 void CstatsInit(argv)
485 char **argv;
486 {
487
488 #ifdef MEMMONITOR
489   CpvInitialize(mmulong,MemoryUsage);
490   CpvAccess(MemoryUsage) = 0;
491   CpvInitialize(mmulong,HiWaterMark);
492   CpvAccess(HiWaterMark) = 0;
493   CpvInitialize(mmulong,ReportedHiWaterMark);
494   CpvAccess(ReportedHiWaterMark) = 0;
495   CpvInitialize(int,AllocCount);
496   CpvAccess(AllocCount) = 0;
497   CpvInitialize(int,BlocksAllocated);
498   CpvAccess(BlocksAllocated) = 0;
499 #endif
500
501   CpvInitialize(int, CstatsMaxChareQueueLength);
502   CpvInitialize(int, CstatsMaxForChareQueueLength);
503   CpvInitialize(int, CstatsMaxFixedChareQueueLength);
504   CpvInitialize(int, CstatPrintQueueStatsFlag);
505   CpvInitialize(int, CstatPrintMemStatsFlag);
506
507   CpvAccess(CstatsMaxChareQueueLength) = 0;
508   CpvAccess(CstatsMaxForChareQueueLength) = 0;
509   CpvAccess(CstatsMaxFixedChareQueueLength) = 0;
510   CpvAccess(CstatPrintQueueStatsFlag) = 0;
511   CpvAccess(CstatPrintMemStatsFlag) = 0;
512
513 #if 0
514   if (CmiGetArgFlagDesc(argv,"+mems", "Print memory statistics at shutdown"))
515     CpvAccess(CstatPrintMemStatsFlag)=1;
516   if (CmiGetArgFlagDesc(argv,"+qs", "Print queue statistics at shutdown"))
517     CpvAccess(CstatPrintQueueStatsFlag)=1;
518 #endif
519 }
520
521 int CstatMemory(i)
522 int i;
523 {
524   return 0;
525 }
526
527 int CstatPrintQueueStats()
528 {
529   return CpvAccess(CstatPrintQueueStatsFlag);
530 }
531
532 int CstatPrintMemStats()
533 {
534   return CpvAccess(CstatPrintMemStatsFlag);
535 }
536
537 /*****************************************************************************
538  *
539  * Cmi handler registration
540  *
541  *****************************************************************************/
542
543 CpvDeclare(CmiHandlerInfo*, CmiHandlerTable);
544 CpvStaticDeclare(int  , CmiHandlerCount);
545 CpvStaticDeclare(int  , CmiHandlerLocal);
546 CpvStaticDeclare(int  , CmiHandlerGlobal);
547 CpvDeclare(int,         CmiHandlerMax);
548
549 static void CmiExtendHandlerTable(int atLeastLen) {
550     int max = CpvAccess(CmiHandlerMax);
551     int newmax = (atLeastLen+(atLeastLen>>2)+32);
552     int bytes = max*sizeof(CmiHandlerInfo);
553     int newbytes = newmax*sizeof(CmiHandlerInfo);
554     CmiHandlerInfo *nu = (CmiHandlerInfo*)malloc(newbytes);
555     CmiHandlerInfo *tab = CpvAccess(CmiHandlerTable);
556     _MEMCHECK(nu);
557     memcpy(nu, tab, bytes);
558     memset(((char *)nu)+bytes, 0, (newbytes-bytes));
559     free(tab); tab=nu;
560     CpvAccess(CmiHandlerTable) = tab;
561     CpvAccess(CmiHandlerMax) = newmax;
562 }
563
564 void CmiNumberHandler(int n, CmiHandler h)
565 {
566   CmiHandlerInfo *tab;
567   if (n >= CpvAccess(CmiHandlerMax)) CmiExtendHandlerTable(n);
568   tab = CpvAccess(CmiHandlerTable);
569   tab[n].hdlr = (CmiHandlerEx)h; /* LIE!  This assumes extra pointer will be ignored!*/
570   tab[n].userPtr = 0;
571 }
572 void CmiNumberHandlerEx(int n, CmiHandlerEx h,void *userPtr) {
573   CmiHandlerInfo *tab;
574   if (n >= CpvAccess(CmiHandlerMax)) CmiExtendHandlerTable(n);
575   tab = CpvAccess(CmiHandlerTable);
576   tab[n].hdlr = h;
577   tab[n].userPtr=userPtr;
578 }
579
580 #if CMI_LOCAL_GLOBAL_AVAILABLE /*Leave room for local and global handlers*/
581 #  define DIST_BETWEEN_HANDLERS 3
582 #else /*No local or global handlers; ordinary handlers are back-to-back*/
583 #  define DIST_BETWEEN_HANDLERS 1
584 #endif
585
586 int CmiRegisterHandler(CmiHandler h)
587 {
588   int Count = CpvAccess(CmiHandlerCount);
589   CmiNumberHandler(Count, h);
590   CpvAccess(CmiHandlerCount) = Count+DIST_BETWEEN_HANDLERS;
591   return Count;
592 }
593 int CmiRegisterHandlerEx(CmiHandlerEx h,void *userPtr)
594 {
595   int Count = CpvAccess(CmiHandlerCount);
596   CmiNumberHandlerEx(Count, h, userPtr);
597   CpvAccess(CmiHandlerCount) = Count+DIST_BETWEEN_HANDLERS;
598   return Count;
599 }
600
601
602 #if CMI_LOCAL_GLOBAL_AVAILABLE
603 int CmiRegisterHandlerLocal(h)
604 CmiHandler h;
605 {
606   int Local = CpvAccess(CmiHandlerLocal);
607   CmiNumberHandler(Local, h);
608   CpvAccess(CmiHandlerLocal) = Local+3;
609   return Local;
610 }
611
612 int CmiRegisterHandlerGlobal(h)
613 CmiHandler h;
614 {
615   int Global = CpvAccess(CmiHandlerGlobal);
616   if (CmiMyPe()!=0) 
617     CmiError("CmiRegisterHandlerGlobal must only be called on PE 0.\n");
618   CmiNumberHandler(Global, h);
619   CpvAccess(CmiHandlerGlobal) = Global+3;
620   return Global;
621 }
622 #endif
623
624 static void _cmiZeroHandler(void *msg) {
625         CmiAbort("Converse zero handler executed-- was a message corrupted?\n");
626 }
627
628 static void CmiHandlerInit()
629 {
630   CpvInitialize(CmiHandlerInfo *, CmiHandlerTable);
631   CpvInitialize(int         , CmiHandlerCount);
632   CpvInitialize(int         , CmiHandlerLocal);
633   CpvInitialize(int         , CmiHandlerGlobal);
634   CpvInitialize(int         , CmiHandlerMax);
635   CpvAccess(CmiHandlerCount)  = 0;
636   CpvAccess(CmiHandlerLocal)  = 1;
637   CpvAccess(CmiHandlerGlobal) = 2;
638   CpvAccess(CmiHandlerMax) = 0; /* Table will be extended on the first registration*/
639   CpvAccess(CmiHandlerTable) = NULL;
640   CmiRegisterHandler((CmiHandler)_cmiZeroHandler);
641 }
642
643
644 /******************************************************************************
645  *
646  * CmiTimer
647  *
648  * Here are two possible implementations of CmiTimer.  Some machines don't
649  * select either, and define the timer in machine.c instead.
650  *
651  *****************************************************************************/
652
653 #if CMK_TIMER_USE_TIMES
654
655 CpvStaticDeclare(double, clocktick);
656 CpvStaticDeclare(int,inittime_wallclock);
657 CpvStaticDeclare(int,inittime_virtual);
658
659 int CmiTimerIsSynchronized()
660 {
661   return 0;
662 }
663
664 void CmiTimerInit()
665 {
666   struct tms temp;
667   CpvInitialize(double, clocktick);
668   CpvInitialize(int, inittime_wallclock);
669   CpvInitialize(int, inittime_virtual);
670   CpvAccess(inittime_wallclock) = times(&temp);
671   CpvAccess(inittime_virtual) = temp.tms_utime + temp.tms_stime;
672   CpvAccess(clocktick) = 1.0 / (sysconf(_SC_CLK_TCK));
673 }
674
675 double CmiWallTimer()
676 {
677   struct tms temp;
678   double currenttime;
679   int now;
680
681   now = times(&temp);
682   currenttime = (now - CpvAccess(inittime_wallclock)) * CpvAccess(clocktick);
683   return (currenttime);
684 }
685
686 double CmiCpuTimer()
687 {
688   struct tms temp;
689   double currenttime;
690   int now;
691
692   times(&temp);
693   now = temp.tms_stime + temp.tms_utime;
694   currenttime = (now - CpvAccess(inittime_virtual)) * CpvAccess(clocktick);
695   return (currenttime);
696 }
697
698 double CmiTimer()
699 {
700   return CmiCpuTimer();
701 }
702
703 #endif
704
705 #if CMK_TIMER_USE_GETRUSAGE
706
707 static double inittime_wallclock;
708 CpvStaticDeclare(double, inittime_virtual);
709
710 int CmiTimerIsSynchronized()
711 {
712   return 0;
713 }
714
715 void CmiTimerInit()
716 {
717   struct timeval tv;
718   struct rusage ru;
719   CpvInitialize(double, inittime_virtual);
720
721   /* try to synchronize calling barrier */
722   CmiBarrier();
723   CmiBarrier();
724   CmiBarrier();
725
726   gettimeofday(&tv,0);
727   inittime_wallclock = (tv.tv_sec * 1.0) + (tv.tv_usec*0.000001);
728   getrusage(0, &ru); 
729   CpvAccess(inittime_virtual) =
730     (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
731     (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
732
733   CmiBarrierZero();
734 }
735
736 double CmiCpuTimer()
737 {
738   struct rusage ru;
739   double currenttime;
740
741   getrusage(0, &ru);
742   currenttime =
743     (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
744     (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
745   return currenttime - CpvAccess(inittime_virtual);
746 }
747
748 double CmiWallTimer()
749 {
750   struct timeval tv;
751   double currenttime;
752
753   gettimeofday(&tv,0);
754   currenttime = (tv.tv_sec * 1.0) + (tv.tv_usec * 0.000001);
755   return currenttime - inittime_wallclock;
756 }
757
758 double CmiTimer()
759 {
760   return CmiCpuTimer();
761 }
762
763 #endif
764
765 #if CMK_TIMER_USE_RDTSC
766
767 static double readMHz(void)
768 {
769   double x;
770   char str[1000];
771   char buf[100];
772   FILE *fp = fopen("/proc/cpuinfo", "r");
773   while(fgets(str, 1000, fp)!=0) {
774     if(sscanf(str, "cpu MHz%[^:]",buf)==1)
775     {
776       char *s = strchr(str, ':'); s=s+1;
777       sscanf(s, "%lf", &x);
778       fclose(fp);
779       return x;
780     }
781   }
782   CmiAbort("Cannot read CPU MHz from /proc/cpuinfo file.");
783   return 0.0;
784 }
785
786 double _cpu_speed_factor;
787 CpvStaticDeclare(double, inittime_virtual);
788 CpvStaticDeclare(double, inittime_walltime);
789
790 double  CmiStartTimer(void)
791 {
792   return CpvAccess(inittime_walltime);
793 }
794
795 void CmiTimerInit()
796 {
797   struct rusage ru;
798
799   CmiBarrier();
800   CmiBarrier();
801
802   _cpu_speed_factor = 1.0/(readMHz()*1.0e6); 
803   rdtsc(); rdtsc(); rdtsc(); rdtsc(); rdtsc();
804   CpvInitialize(double, inittime_walltime);
805   CpvAccess(inittime_walltime) = CmiWallTimer();
806   CpvInitialize(double, inittime_virtual);
807   getrusage(0, &ru); 
808   CpvAccess(inittime_virtual) =
809     (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
810     (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
811
812   CmiBarrierZero();
813 }
814
815 double CmiCpuTimer()
816 {
817   struct rusage ru;
818   double currenttime;
819
820   getrusage(0, &ru);
821   currenttime =
822     (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
823     (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
824   return currenttime - CpvAccess(inittime_virtual);
825 }
826
827 #endif
828
829 #if CMK_TIMER_USE_BLUEGENEL
830
831 #include <rts.h>
832
833 #if 0
834 #define SPRN_TBRL 0x10C  // Time Base Read Lower Register (user & sup R/O)
835 #define SPRN_TBRU 0x10D  // Time Base Read Upper Register (user & sup R/O)
836 #define SPRN_PIR  0x11E  // CPU id
837
838 static inline unsigned long long BGLTimebase(void)
839 {
840   unsigned volatile u1, u2, lo;
841   union
842   {
843     struct { unsigned hi, lo; } w;
844     unsigned long long d;
845   } result;
846                                                                                 
847   do {
848     asm volatile ("mfspr %0,%1" : "=r" (u1) : "i" (SPRN_TBRU));
849     asm volatile ("mfspr %0,%1" : "=r" (lo) : "i" (SPRN_TBRL));
850     asm volatile ("mfspr %0,%1" : "=r" (u2) : "i" (SPRN_TBRU));
851   } while (u1!=u2);
852                                                                                 
853   result.w.lo = lo;
854   result.w.hi = u2;
855   return result.d;
856 }
857 #endif
858
859 static unsigned long long inittime_wallclock;
860 CpvStaticDeclare(double, clocktick);
861
862 int CmiTimerIsSynchronized()
863 {
864   return 0;
865 }
866
867 void CmiTimerInit()
868 {
869   BGLPersonality dst;
870   CpvInitialize(double, clocktick);
871   int size = sizeof(BGLPersonality);
872   rts_get_personality(&dst, size);
873   CpvAccess(clocktick) = 1.0 / dst.clockHz;
874
875   /* try to synchronize calling barrier */
876   CmiBarrier();
877   CmiBarrier();
878   CmiBarrier();
879
880   inittime_wallclock = rts_get_timebase();
881 }
882
883 double CmiWallTimer()
884 {
885   unsigned long long currenttime;
886   currenttime = rts_get_timebase();
887   return CpvAccess(clocktick)*(currenttime-inittime_wallclock);
888 }
889
890 double CmiCpuTimer()
891 {
892   return CmiWallTimer();
893 }
894
895 double CmiTimer()
896 {
897   return CmiWallTimer();
898 }
899
900 #endif
901
902 #if CMK_TIMER_USE_WIN32API
903
904 CpvStaticDeclare(double, inittime_wallclock);
905 CpvStaticDeclare(double, inittime_virtual);
906
907 void CmiTimerInit()
908 {
909 #ifdef __CYGWIN__
910         struct timeb tv;
911 #else
912         struct _timeb tv;
913 #endif
914         clock_t       ru;
915
916         CpvInitialize(double, inittime_wallclock);
917         CpvInitialize(double, inittime_virtual);
918         _ftime(&tv);
919         CpvAccess(inittime_wallclock) = tv.time*1.0 + tv.millitm*0.001;
920         ru = clock();
921         CpvAccess(inittime_virtual) = ((double) ru)/CLOCKS_PER_SEC;
922 }
923
924 double CmiCpuTimer()
925 {
926         clock_t ru;
927         double currenttime;
928
929         ru = clock();
930         currenttime = (double) ru/CLOCKS_PER_SEC;
931
932         return currenttime - CpvAccess(inittime_virtual);
933 }
934
935 double CmiWallTimer()
936 {
937 #ifdef __CYGWIN__
938         struct timeb tv;
939 #else
940         struct _timeb tv;
941 #endif
942         double currenttime;
943
944         _ftime(&tv);
945         currenttime = tv.time*1.0 + tv.millitm*0.001;
946
947         return currenttime - CpvAccess(inittime_wallclock);
948 }
949         
950
951 double CmiTimer()
952 {
953         return CmiCpuTimer();
954 }
955
956 #endif
957
958 #if CMK_TIMER_USE_RTC
959
960 #if __crayx1
961  /* For _rtc() on Cray X1 */
962 #include <intrinsics.h>
963 #endif
964
965 static double clocktick;
966 CpvStaticDeclare(long long, inittime_wallclock);
967
968 void CmiTimerInit()
969 {
970   CpvInitialize(long long, inittime_wallclock);
971   CpvAccess(inittime_wallclock) = _rtc();
972   clocktick = 1.0 / (double)(sysconf(_SC_SV2_USER_TIME_RATE));
973 }
974
975 double CmiWallTimer()
976 {
977   long long now;
978
979   now = _rtc();
980   return (clocktick * (now - CpvAccess(inittime_wallclock)));
981 }
982
983 double CmiCpuTimer()
984 {
985   return CmiWallTimer();
986 }
987
988 double CmiTimer()
989 {
990   return CmiCpuTimer();
991 }
992
993 #endif
994
995 #ifndef CMK_USE_SPECIAL_MESSAGE_QUEUE_CHECK
996 /** Return 1 if our outgoing message queue 
997    for this node is longer than this many bytes. */
998 int CmiLongSendQueue(int forNode,int longerThanBytes) {
999   return 0;
1000 }
1001 #endif
1002
1003 #if CMK_SIGNAL_USE_SIGACTION
1004 #include <signal.h>
1005 void CmiSignal(sig1, sig2, sig3, handler)
1006 int sig1, sig2, sig3;
1007 void (*handler)();
1008 {
1009   struct sigaction in, out ;
1010   in.sa_handler = handler;
1011   sigemptyset(&in.sa_mask);
1012   if (sig1) sigaddset(&in.sa_mask, sig1);
1013   if (sig2) sigaddset(&in.sa_mask, sig2);
1014   if (sig3) sigaddset(&in.sa_mask, sig3);
1015   in.sa_flags = 0;
1016   if (sig1) if (sigaction(sig1, &in, &out)<0) exit(1);
1017   if (sig2) if (sigaction(sig2, &in, &out)<0) exit(1);
1018   if (sig3) if (sigaction(sig3, &in, &out)<0) exit(1);
1019 }
1020 #endif
1021
1022 #if CMK_SIGNAL_USE_SIGACTION_WITH_RESTART
1023 #include <signal.h>
1024 void CmiSignal(sig1, sig2, sig3, handler)
1025 int sig1, sig2, sig3;
1026 void (*handler)();
1027 {
1028   struct sigaction in, out ;
1029   in.sa_handler = handler;
1030   sigemptyset(&in.sa_mask);
1031   if (sig1) sigaddset(&in.sa_mask, sig1);
1032   if (sig2) sigaddset(&in.sa_mask, sig2);
1033   if (sig3) sigaddset(&in.sa_mask, sig3);
1034   in.sa_flags = SA_RESTART;
1035   if (sig1) if (sigaction(sig1, &in, &out)<0) exit(1);
1036   if (sig2) if (sigaction(sig2, &in, &out)<0) exit(1);
1037   if (sig3) if (sigaction(sig3, &in, &out)<0) exit(1);
1038 }
1039 #endif
1040
1041 /*****************************************************************************
1042  *
1043  * The following is the CsdScheduler function.  A common
1044  * implementation is provided below.  The machine layer can provide an
1045  * alternate implementation if it so desires.
1046  *
1047  * void CmiDeliversInit()
1048  *
1049  *      - CmiInit promises to call this before calling CmiDeliverMsgs
1050  *        or any of the other functions in this section.
1051  *
1052  * int CmiDeliverMsgs(int maxmsgs)
1053  *
1054  *      - CmiDeliverMsgs will retrieve up to maxmsgs that were transmitted
1055  *        with the Cmi, and will invoke their handlers.  It does not wait
1056  *        if no message is unavailable.  Instead, it returns the quantity
1057  *        (maxmsgs-delivered), where delivered is the number of messages it
1058  *        delivered.
1059  *
1060  * void CmiDeliverSpecificMsg(int handlerno)
1061  *
1062  *      - Waits for a message with the specified handler to show up, then
1063  *        invokes the message's handler.  Note that unlike CmiDeliverMsgs,
1064  *        This function _does_ wait.
1065  *
1066  * For this common implementation to work, the machine layer must provide the
1067  * following:
1068  *
1069  * void *CmiGetNonLocal()
1070  *
1071  *      - returns a message just retrieved from some other PE, not from
1072  *        local.  If no such message exists, returns 0.
1073  *
1074  * CpvExtern(CdsFifo, CmiLocalQueue);
1075  *
1076  *      - a FIFO queue containing all messages from the local processor.
1077  *
1078  *****************************************************************************/
1079
1080 void CsdBeginIdle(void)
1081 {
1082   CcdCallBacks();
1083   _LOG_E_PROC_IDLE();   /* projector */
1084   CcdRaiseCondition(CcdPROCESSOR_BEGIN_IDLE) ;
1085 }
1086
1087 void CsdStillIdle(void)
1088 {
1089   CcdRaiseCondition(CcdPROCESSOR_STILL_IDLE);
1090 }
1091
1092 void CsdEndIdle(void)
1093 {
1094   _LOG_E_PROC_BUSY();   /* projector */
1095   CcdRaiseCondition(CcdPROCESSOR_BEGIN_BUSY) ;
1096 }
1097
1098 #if CMK_MEM_CHECKPOINT
1099 #define MESSAGE_PHASE_CHECK     \
1100         {       \
1101           int phase = CmiGetRestartPhase(msg);  \
1102           if (phase < cur_restart_phase) {      \
1103             /*CmiPrintf("[%d] discard message of phase %d cur_restart_phase:%d handler:%d. \n", CmiMyPe(), phase, cur_restart_phase, handler);*/        \
1104             CmiFree(msg);       \
1105             return;     \
1106           }     \
1107         }
1108 #else
1109 #define MESSAGE_PHASE_CHECK
1110 #endif
1111
1112 void CmiHandleMessage(void *msg)
1113 {
1114 /* this is wrong because it counts the Charm++ messages in sched queue
1115         CpvAccess(cQdState)->mProcessed++;
1116 */
1117         CmiHandlerInfo *h;
1118 #ifndef CMK_OPTIMIZE
1119         CmiUInt2 handler=CmiGetHandler(msg); /* Save handler for use after msg is gone */
1120         _LOG_E_HANDLER_BEGIN(handler); /* projector */
1121 #endif
1122
1123         MESSAGE_PHASE_CHECK
1124
1125         h=&CmiGetHandlerInfo(msg);
1126         (h->hdlr)(msg,h->userPtr);
1127 #ifndef CMK_OPTIMIZE
1128         _LOG_E_HANDLER_END(handler);    /* projector */
1129 #endif
1130 }
1131
1132 #if CMK_CMIDELIVERS_USE_COMMON_CODE
1133
1134 void CmiDeliversInit()
1135 {
1136 }
1137
1138 int CmiDeliverMsgs(int maxmsgs)
1139 {
1140   return CsdScheduler(maxmsgs);
1141 }
1142
1143 #if CMK_OBJECT_QUEUE_AVAILABLE
1144 CpvDeclare(void *, CsdObjQueue);
1145 #endif
1146
1147 void CsdSchedulerState_new(CsdSchedulerState_t *s)
1148 {
1149 #if CMK_OBJECT_QUEUE_AVAILABLE
1150         s->objQ=CpvAccess(CsdObjQueue);
1151 #endif
1152         s->localQ=CpvAccess(CmiLocalQueue);
1153         s->schedQ=CpvAccess(CsdSchedQueue);
1154         s->localCounter=&(CpvAccess(CsdLocalCounter));
1155 #if CMK_NODE_QUEUE_AVAILABLE
1156         s->nodeQ=CsvAccess(CsdNodeQueue);
1157         s->nodeLock=CsvAccess(CsdNodeQueueLock);
1158 #endif
1159         
1160 }
1161
1162 void *CsdNextMessage(CsdSchedulerState_t *s) {
1163         void *msg;
1164         if((*(s->localCounter))-- >0)
1165           {
1166               /* This avoids a race condition with migration detected by megatest*/
1167               msg=CdsFifo_Dequeue(s->localQ);
1168               if (msg!=NULL)
1169                 {
1170                   CpvAccess(cQdState)->mProcessed++;
1171                   return msg;       
1172                 }
1173               CqsDequeue(s->schedQ,(void **)&msg);
1174               if (msg!=NULL) return msg;
1175           }
1176         
1177         *(s->localCounter)=CsdLocalMax;
1178         if ( NULL!=(msg=CmiGetNonLocal()) || 
1179              NULL!=(msg=CdsFifo_Dequeue(s->localQ)) ) {
1180             CpvAccess(cQdState)->mProcessed++;
1181             return msg;
1182         }
1183 #if CMK_NODE_QUEUE_AVAILABLE
1184         if (NULL!=(msg=CmiGetNonLocalNodeQ())) return msg;
1185         if (!CqsEmpty(s->nodeQ)
1186          && !CqsPrioGT(CqsGetPriority(s->nodeQ),
1187                        CqsGetPriority(s->schedQ))) {
1188           CmiLock(s->nodeLock);
1189           CqsDequeue(s->nodeQ,(void **)&msg);
1190           CmiUnlock(s->nodeLock);
1191           if (msg!=NULL) return msg;
1192         }
1193 #endif
1194 #if CMK_OBJECT_QUEUE_AVAILABLE
1195         if (NULL!=(msg=CdsFifo_Dequeue(s->objQ))) {
1196           return msg;
1197         }
1198 #endif
1199         if(!CsdLocalMax) {
1200           CqsDequeue(s->schedQ,(void **)&msg);
1201             if (msg!=NULL) return msg;      
1202         }
1203
1204         return NULL;
1205
1206 }
1207
1208 int CsdScheduler(int maxmsgs)
1209 {
1210         if (maxmsgs<0) CsdScheduleForever();    
1211         else if (maxmsgs==0)
1212                 CsdSchedulePoll();
1213         else /*(maxmsgs>0)*/ 
1214                 return CsdScheduleCount(maxmsgs);
1215         return 0;
1216 }
1217
1218 /*Declare the standard scheduler housekeeping*/
1219 #define SCHEDULE_TOP \
1220       void *msg;\
1221       int cycle = CpvAccess(CsdStopFlag); \
1222       CsdSchedulerState_t state;\
1223       CsdSchedulerState_new(&state);\
1224
1225 /*A message is available-- process it*/
1226 #define SCHEDULE_MESSAGE \
1227       CmiHandleMessage(msg);\
1228       if (CpvAccess(CsdStopFlag) != cycle) break;\
1229
1230 /*No message available-- go (or remain) idle*/
1231 #define SCHEDULE_IDLE \
1232       if (!isIdle) {isIdle=1;CsdBeginIdle();}\
1233       else CsdStillIdle();\
1234       if (CpvAccess(CsdStopFlag) != cycle) {\
1235         CsdEndIdle();\
1236         break;\
1237       }\
1238
1239 void CsdScheduleForever(void)
1240 {
1241   int isIdle=0;
1242   SCHEDULE_TOP
1243   while (1) {
1244     msg = CsdNextMessage(&state);
1245     if (msg) { /*A message is available-- process it*/
1246       if (isIdle) {isIdle=0;CsdEndIdle();}
1247       SCHEDULE_MESSAGE
1248     } else { /*No message available-- go (or remain) idle*/
1249       SCHEDULE_IDLE
1250     }
1251     CsdPeriodic();
1252   }
1253 }
1254 int CsdScheduleCount(int maxmsgs)
1255 {
1256   int isIdle=0;
1257   SCHEDULE_TOP
1258   while (1) {
1259     msg = CsdNextMessage(&state);
1260     if (msg) { /*A message is available-- process it*/
1261       if (isIdle) {isIdle=0;CsdEndIdle();}
1262       maxmsgs--; 
1263       SCHEDULE_MESSAGE
1264       if (maxmsgs==0) break;
1265     } else { /*No message available-- go (or remain) idle*/
1266       SCHEDULE_IDLE
1267     }
1268     CsdPeriodic();
1269   }
1270   return maxmsgs;
1271 }
1272
1273 void CsdSchedulePoll(void)
1274 {
1275   SCHEDULE_TOP
1276   while (1)
1277   {
1278         CsdPeriodic();
1279         if (NULL!=(msg = CsdNextMessage(&state)))
1280         {
1281              SCHEDULE_MESSAGE 
1282         }
1283         else break;
1284   }
1285 }
1286
1287 void CmiDeliverSpecificMsg(handler)
1288 int handler;
1289 {
1290   int *msg; int side;
1291   void *localqueue = CpvAccess(CmiLocalQueue);
1292  
1293   side = 0;
1294   while (1) {
1295     CsdPeriodic();
1296     side ^= 1;
1297     if (side) msg = CmiGetNonLocal();
1298     else      msg = CdsFifo_Dequeue(localqueue);
1299     if (msg) {
1300       if (CmiGetHandler(msg)==handler) {
1301         CpvAccess(cQdState)->mProcessed++;
1302         CmiHandleMessage(msg);
1303         return;
1304       } else {
1305         CdsFifo_Enqueue(localqueue, msg);
1306       }
1307     }
1308   }
1309 }
1310  
1311 #endif /* CMK_CMIDELIVERS_USE_COMMON_CODE */
1312
1313 /***************************************************************************
1314  *
1315  * Standin Schedulers.
1316  *
1317  * We use the following strategy to make sure somebody's always running
1318  * the scheduler (CsdScheduler).  Initially, we assume the main thread
1319  * is responsible for this.  If the main thread blocks, we create a
1320  * "standin scheduler" thread to replace it.  If the standin scheduler
1321  * blocks, we create another standin scheduler to replace that one,
1322  * ad infinitum.  Collectively, the main thread and all the standin
1323  * schedulers are called "scheduling threads".
1324  *
1325  * Suppose the main thread is blocked waiting for data, and a standin
1326  * scheduler is running instead.  Suppose, then, that the data shows
1327  * up and the main thread is CthAwakened.  This causes a token to be
1328  * pushed into the queue.  When the standin pulls the token from the
1329  * queue and handles it, the standin goes to sleep, and control shifts
1330  * back to the main thread.  In this way, unnecessary standins are put
1331  * back to sleep.  These sleeping standins are stored on the
1332  * CthSleepingStandins list.
1333  *
1334  ***************************************************************************/
1335
1336 CpvStaticDeclare(CthThread, CthMainThread);
1337 CpvStaticDeclare(CthThread, CthSchedulingThread);
1338 CpvStaticDeclare(CthThread, CthSleepingStandins);
1339 CpvStaticDeclare(int      , CthResumeNormalThreadIdx);
1340 CpvStaticDeclare(int      , CthResumeSchedulingThreadIdx);
1341
1342
1343 void CthStandinCode()
1344 {
1345   while (1) CsdScheduler(0);
1346 }
1347
1348 CthThread CthSuspendNormalThread()
1349 {
1350   return CpvAccess(CthSchedulingThread);
1351 }
1352
1353 void CthEnqueueSchedulingThread(CthThread t, int, int, unsigned int*);
1354 CthThread CthSuspendSchedulingThread();
1355
1356 CthThread CthSuspendSchedulingThread()
1357 {
1358   CthThread succ = CpvAccess(CthSleepingStandins);
1359
1360   if (succ) {
1361     CpvAccess(CthSleepingStandins) = CthGetNext(succ);
1362   } else {
1363     succ = CthCreate(CthStandinCode, 0, 256000);
1364     CthSetStrategy(succ,
1365                    CthEnqueueSchedulingThread,
1366                    CthSuspendSchedulingThread);
1367   }
1368   
1369   CpvAccess(CthSchedulingThread) = succ;
1370   return succ;
1371 }
1372
1373 void CthResumeNormalThread(CthThread t)
1374 {
1375 #ifndef CMK_OPTIMIZE
1376 #if ! CMK_TRACE_IN_CHARM
1377   if(CpvAccess(traceOn))
1378     CthTraceResume(t);
1379 /*    if(CpvAccess(_traceCoreOn)) 
1380                 resumeTraceCore();*/
1381 #endif
1382 #endif
1383     
1384   CthResume(t);
1385 }
1386
1387 void CthResumeSchedulingThread(CthThread t)
1388 {
1389   CthThread me = CthSelf();
1390   if (me == CpvAccess(CthMainThread)) {
1391     CthEnqueueSchedulingThread(me,CQS_QUEUEING_FIFO, 0, 0);
1392   } else {
1393     CthSetNext(me, CpvAccess(CthSleepingStandins));
1394     CpvAccess(CthSleepingStandins) = me;
1395   }
1396   CpvAccess(CthSchedulingThread) = t;
1397 #ifndef CMK_OPTIMIZE
1398 #if ! CMK_TRACE_IN_CHARM
1399   if(CpvAccess(traceOn))
1400     CthTraceResume(t);
1401 /*    if(CpvAccess(_traceCoreOn)) 
1402                 resumeTraceCore();*/
1403 #endif
1404 #endif
1405   CthResume(t);
1406 }
1407
1408 void CthEnqueueNormalThread(CthThread t, int s, 
1409                                    int pb,unsigned int *prio)
1410 {
1411   CmiSetHandler(t, CpvAccess(CthResumeNormalThreadIdx));
1412   CsdEnqueueGeneral(t, s, pb, prio);
1413 }
1414
1415 void CthEnqueueSchedulingThread(CthThread t, int s, 
1416                                        int pb,unsigned int *prio)
1417 {
1418   CmiSetHandler(t, CpvAccess(CthResumeSchedulingThreadIdx));
1419   CsdEnqueueGeneral(t, s, pb, prio);
1420 }
1421
1422 void CthSetStrategyDefault(CthThread t)
1423 {
1424   CthSetStrategy(t,
1425                  CthEnqueueNormalThread,
1426                  CthSuspendNormalThread);
1427 }
1428
1429 void CthSchedInit()
1430 {
1431   CpvInitialize(CthThread, CthMainThread);
1432   CpvInitialize(CthThread, CthSchedulingThread);
1433   CpvInitialize(CthThread, CthSleepingStandins);
1434   CpvInitialize(int      , CthResumeNormalThreadIdx);
1435   CpvInitialize(int      , CthResumeSchedulingThreadIdx);
1436
1437   CpvAccess(CthMainThread) = CthSelf();
1438   CpvAccess(CthSchedulingThread) = CthSelf();
1439   CpvAccess(CthSleepingStandins) = 0;
1440   CpvAccess(CthResumeNormalThreadIdx) =
1441     CmiRegisterHandler((CmiHandler)CthResumeNormalThread);
1442   CpvAccess(CthResumeSchedulingThreadIdx) =
1443     CmiRegisterHandler((CmiHandler)CthResumeSchedulingThread);
1444   CthSetStrategy(CthSelf(),
1445                  CthEnqueueSchedulingThread,
1446                  CthSuspendSchedulingThread);
1447 }
1448
1449 void CsdInit(argv)
1450   char **argv;
1451 {
1452   CpvInitialize(void *, CsdSchedQueue);
1453   CpvInitialize(int,   CsdStopFlag);
1454   CpvInitialize(int,   CsdLocalCounter);
1455   if(!CmiGetArgIntDesc(argv,"+csdLocalMax",&CsdLocalMax,"Set the max number of local messages to process before forcing a check for remote messages."))
1456     {
1457       CsdLocalMax= CSD_LOCAL_MAX_DEFAULT;
1458     }
1459   CpvAccess(CsdLocalCounter) = CsdLocalMax;
1460   CpvAccess(CsdSchedQueue) = (void *)CqsCreate();
1461
1462 #if CMK_OBJECT_QUEUE_AVAILABLE
1463   CpvInitialize(void *,CsdObjQueue);
1464   CpvAccess(CsdObjQueue) = CdsFifo_Create();
1465 #endif
1466
1467 #if CMK_NODE_QUEUE_AVAILABLE
1468   CsvInitialize(CmiLock, CsdNodeQueueLock);
1469   CsvInitialize(void *, CsdNodeQueue);
1470   if (CmiMyRank() ==0) {
1471         CsvAccess(CsdNodeQueueLock) = CmiCreateLock();
1472         CsvAccess(CsdNodeQueue) = (void *)CqsCreate();
1473   }
1474   CmiNodeAllBarrier();
1475 #endif
1476
1477   CpvAccess(CsdStopFlag)  = 0;
1478 }
1479
1480
1481 /*****************************************************************************
1482  *
1483  * Vector Send
1484  *
1485  * All the buffers are padded to 8 bytes. This helps in most systems where
1486  * analigned memory either does not work, or works slowly.
1487  *
1488  * The last parameter "system" is by default at zero, in which case the normal
1489  * messages are sent. If it is set to 1, the CmiChunkHeader prepended to every
1490  * CmiAllocced message will also be sent (except for the first one). Useful for
1491  * AllToAll communication, and other system features.
1492  *
1493  ****************************************************************************/
1494
1495 #define PAD8(x)    ((x+0x07)&(~0x07))
1496
1497 #if CMK_VECTOR_SEND_USES_COMMON_CODE
1498
1499 void CmiSyncVectorSendSystem(destPE, n, sizes, msgs, system)
1500 int destPE, n;
1501 int *sizes;
1502 char **msgs;
1503 int system;
1504 {
1505   int i, total;
1506   char *mesg, *tmp;
1507   
1508   for(i=0,total=0;i<n;i++) total += PAD8(sizes[i]);
1509   if (system) total += (n-1)*sizeof(CmiChunkHeader);
1510   mesg = (char *) CmiAlloc(total);
1511   tmp=mesg;
1512   if (system) {
1513     memcpy(tmp, msgs[0], sizes[0]);
1514     tmp += PAD8(sizes[i]);
1515     for (i=1; i<n; ++i) {
1516       memcpy(tmp, msgs[i]-sizeof(CmiChunkHeader), sizes[i]+sizeof(CmiChunkHeader));
1517       tmp += PAD8(sizes[i])+sizeof(CmiChunkHeader);
1518     }
1519   } else {
1520     for(i=0;i<n;i++) {
1521       memcpy(tmp, msgs[i],sizes[i]);
1522       tmp += PAD8(sizes[i]);
1523     }
1524   }
1525   CmiSyncSendAndFree(destPE, total, mesg);
1526 }
1527
1528 CmiCommHandle CmiAsyncVectorSendSystem(destPE, n, sizes, msgs, system)
1529 int destPE, n;
1530 int *sizes;
1531 char **msgs;
1532 int system;
1533 {
1534   CmiSyncVectorSendSystem(destPE,n,sizes,msgs,system);
1535   return NULL;
1536 }
1537
1538 void CmiSyncVectorSendAndFreeSystem(destPE, n, sizes, msgs, system)
1539 int destPE, n;
1540 int *sizes;
1541 char **msgs;
1542 int system;
1543 {
1544   int i;
1545
1546   CmiSyncVectorSendSystem(destPE,n,sizes,msgs,system);
1547   for(i=0;i<n;i++) CmiFree(msgs[i]);
1548   CmiFree(sizes);
1549   CmiFree(msgs);
1550 }
1551
1552 #endif
1553
1554 void CmiSyncVectorSend(int destPE, int n, int *sizes, char **msgs) {
1555   CmiSyncVectorSendSystem(destPE, n, sizes, msgs, 0);
1556 }
1557
1558 void CmiASyncVectorSend(int destPE, int n, int *sizes, char **msgs) {
1559   CmiAsyncVectorSendSystem(destPE, n, sizes, msgs, 0);
1560 }
1561
1562 void CmiSyncVectorSendAndFree(int destPE, int n, int *sizes, char **msgs) {
1563   CmiSyncVectorSendAndFreeSystem(destPE, n, sizes, msgs, 0);
1564 }
1565
1566 /*****************************************************************************
1567  *
1568  * Multicast groups
1569  *
1570  ****************************************************************************/
1571
1572 #if CMK_MULTICAST_DEF_USE_COMMON_CODE
1573
1574 typedef struct GroupDef
1575 {
1576   union {
1577     char core[CmiMsgHeaderSizeBytes];
1578     struct GroupDef *next;
1579   } core;
1580   CmiGroup group;
1581   int npes;
1582   int pes[1];
1583 }
1584 *GroupDef;
1585
1586 #define GROUPTAB_SIZE 101
1587
1588 CpvStaticDeclare(int, CmiGroupHandlerIndex);
1589 CpvStaticDeclare(int, CmiGroupCounter);
1590 CpvStaticDeclare(GroupDef *, CmiGroupTable);
1591
1592 void CmiGroupHandler(GroupDef def)
1593 {
1594   /* receive group definition, insert into group table */
1595   GroupDef *table = CpvAccess(CmiGroupTable);
1596   unsigned int hashval, bucket;
1597   hashval = (def->group.id ^ def->group.pe);
1598   bucket = hashval % GROUPTAB_SIZE;
1599   def->core.next = table[bucket];
1600   table[bucket] = def;
1601 }
1602
1603 CmiGroup CmiEstablishGroup(int npes, int *pes)
1604 {
1605   /* build new group definition, broadcast it */
1606   CmiGroup grp; GroupDef def; int len, i;
1607   grp.id = CpvAccess(CmiGroupCounter)++;
1608   grp.pe = CmiMyPe();
1609   len = sizeof(struct GroupDef)+(npes*sizeof(int));
1610   def = (GroupDef)CmiAlloc(len);
1611   def->group = grp;
1612   def->npes = npes;
1613   for (i=0; i<npes; i++)
1614     def->pes[i] = pes[i];
1615   CmiSetHandler(def, CpvAccess(CmiGroupHandlerIndex));
1616   CmiSyncBroadcastAllAndFree(len, def);
1617   return grp;
1618 }
1619
1620 void CmiLookupGroup(CmiGroup grp, int *npes, int **pes)
1621 {
1622   unsigned int hashval, bucket;  GroupDef def;
1623   GroupDef *table = CpvAccess(CmiGroupTable);
1624   hashval = (grp.id ^ grp.pe);
1625   bucket = hashval % GROUPTAB_SIZE;
1626   for (def=table[bucket]; def; def=def->core.next) {
1627     if ((def->group.id == grp.id)&&(def->group.pe == grp.pe)) {
1628       *npes = def->npes;
1629       *pes = def->pes;
1630       return;
1631     }
1632   }
1633   *npes = 0; *pes = 0;
1634 }
1635
1636 void CmiGroupInit()
1637 {
1638   CpvInitialize(int, CmiGroupHandlerIndex);
1639   CpvInitialize(int, CmiGroupCounter);
1640   CpvInitialize(GroupDef *, CmiGroupTable);
1641   CpvAccess(CmiGroupHandlerIndex) = CmiRegisterHandler((CmiHandler)CmiGroupHandler);
1642   CpvAccess(CmiGroupCounter) = 0;
1643   CpvAccess(CmiGroupTable) =
1644     (GroupDef*)calloc(GROUPTAB_SIZE, sizeof(GroupDef));
1645   if (CpvAccess(CmiGroupTable) == 0)
1646     CmiAbort("Memory Allocation Error");
1647 }
1648
1649 #endif
1650
1651 /*****************************************************************************
1652  *
1653  * Common List-Cast and Multicast Code
1654  *
1655  ****************************************************************************/
1656
1657 #if CMK_MULTICAST_LIST_USE_COMMON_CODE
1658
1659 void CmiSyncListSendFn(int npes, int *pes, int len, char *msg)
1660 {
1661   int i;
1662   for(i=0;i<npes;i++) {
1663     CmiSyncSend(pes[i], len, msg);
1664   }
1665 }
1666
1667 CmiCommHandle CmiAsyncListSendFn(int npes, int *pes, int len, char *msg)
1668 {
1669   /* A better asynchronous implementation may be wanted, but at least it works */
1670   CmiSyncListSendFn(npes, pes, len, msg);
1671   return (CmiCommHandle) 0;
1672 }
1673
1674 void CmiFreeListSendFn(int npes, int *pes, int len, char *msg)
1675 {
1676   int i;
1677   for(i=0;i<npes-1;i++) {
1678     CmiSyncSend(pes[i], len, msg);
1679   }
1680   if (npes)
1681     CmiSyncSendAndFree(pes[npes-1], len, msg);
1682   else 
1683     CmiFree(msg);
1684 }
1685
1686 #endif
1687
1688 #if CMK_MULTICAST_GROUP_USE_COMMON_CODE
1689
1690 typedef struct MultiMsg
1691 {
1692   char core[CmiMsgHeaderSizeBytes];
1693   CmiGroup group;
1694   int pos;
1695   int origlen;
1696 }
1697 *MultiMsg;
1698
1699 CpvDeclare(int, CmiMulticastHandlerIndex);
1700
1701 void CmiMulticastDeliver(MultiMsg msg)
1702 {
1703   int npes, *pes; int olen, nlen, pos, child1, child2;
1704   olen = msg->origlen;
1705   nlen = olen + sizeof(struct MultiMsg);
1706   CmiLookupGroup(msg->group, &npes, &pes);
1707   if (pes==0) {
1708     CmiSyncSendAndFree(CmiMyPe(), nlen, msg);
1709     return;
1710   }
1711   if (npes==0) {
1712     CmiFree(msg);
1713     return;
1714   }
1715   if (msg->pos == -1) {
1716     msg->pos=0;
1717     CmiSyncSendAndFree(pes[0], nlen, msg);
1718     return;
1719   }
1720   pos = msg->pos;
1721   child1 = ((pos+1)<<1);
1722   child2 = child1-1;
1723   if (child1 < npes) {
1724     msg->pos = child1;
1725     CmiSyncSend(pes[child1], nlen, msg);
1726   }
1727   if (child2 < npes) {
1728     msg->pos = child2;
1729     CmiSyncSend(pes[child2], nlen, msg);
1730   }
1731   if(olen < sizeof(struct MultiMsg)) {
1732     memcpy(msg, msg+1, olen);
1733   } else {
1734     memcpy(msg, (((char*)msg)+olen), sizeof(struct MultiMsg));
1735   }
1736   CmiSyncSendAndFree(CmiMyPe(), olen, msg);
1737 }
1738
1739 void CmiMulticastHandler(MultiMsg msg)
1740 {
1741   CmiMulticastDeliver(msg);
1742 }
1743
1744 void CmiSyncMulticastFn(CmiGroup grp, int len, char *msg)
1745 {
1746   int newlen; MultiMsg newmsg;
1747   newlen = len + sizeof(struct MultiMsg);
1748   newmsg = (MultiMsg)CmiAlloc(newlen);
1749   if(len < sizeof(struct MultiMsg)) {
1750     memcpy(newmsg+1, msg, len);
1751   } else {
1752     memcpy(newmsg+1, msg+sizeof(struct MultiMsg), len-sizeof(struct MultiMsg));
1753     memcpy(((char *)newmsg+len), msg, sizeof(struct MultiMsg));
1754   }
1755   newmsg->group = grp;
1756   newmsg->origlen = len;
1757   newmsg->pos = -1;
1758   CmiSetHandler(newmsg, CpvAccess(CmiMulticastHandlerIndex));
1759   CmiMulticastDeliver(newmsg);
1760 }
1761
1762 void CmiFreeMulticastFn(CmiGroup grp, int len, char *msg)
1763 {
1764   CmiSyncMulticastFn(grp, len, msg);
1765   CmiFree(msg);
1766 }
1767
1768 CmiCommHandle CmiAsyncMulticastFn(CmiGroup grp, int len, char *msg)
1769 {
1770   CmiError("Async Multicast not implemented.");
1771   return (CmiCommHandle) 0;
1772 }
1773
1774 void CmiMulticastInit()
1775 {
1776   CpvInitialize(int, CmiMulticastHandlerIndex);
1777   CpvAccess(CmiMulticastHandlerIndex) =
1778     CmiRegisterHandler((CmiHandler)CmiMulticastHandler);
1779 }
1780
1781 #endif
1782
1783 /***************************************************************************
1784  *
1785  * Memory Allocation routines 
1786  *
1787  * A block of memory can consist of multiple chunks.  Each chunk has
1788  * a sizefield and a refcount.  The first chunk's refcount is a reference
1789  * count.  That's how many CmiFrees it takes to free the message.
1790  * Subsequent chunks have a refcount which is less than zero.  This is
1791  * the offset back to the start of the first chunk.
1792  *
1793  * Each chunk has a CmiChunkHeader before the user data, with the fields:
1794  *
1795  *  size: The user-allocated size of the chunk, in bytes.
1796  *
1797  *  ref: A magic reference count object. Ordinary blocks start with
1798  *     reference count 1.  When the reference count reaches zero,
1799  *     the block is deleted.  To support nested buffers, the 
1800  *     reference count can also be negative, which means it is 
1801  *     a byte offset to the enclosing buffer's reference count.
1802  *
1803  ***************************************************************************/
1804
1805
1806 void *CmiAlloc(int size)
1807 {
1808   char *res;
1809
1810 #if CONVERSE_VERSION_ELAN
1811   res = (char *) elan_CmiAlloc(size+sizeof(CmiChunkHeader));
1812 #elif CONVERSE_VERSION_VMI
1813   res = (char *) CMI_VMI_CmiAlloc(size+sizeof(CmiChunkHeader));
1814 #elif CONVERSE_POOL
1815   res =(char *) CmiPoolAlloc(size+sizeof(CmiChunkHeader));
1816 #else
1817   res =(char *) malloc_nomigrate(size+sizeof(CmiChunkHeader));
1818 #endif
1819
1820   _MEMCHECK(res);
1821
1822 #ifdef MEMMONITOR
1823   CpvAccess(MemoryUsage) += size+sizeof(CmiChunkHeader);
1824   CpvAccess(AllocCount)++;
1825   CpvAccess(BlocksAllocated)++;
1826   if (CpvAccess(MemoryUsage) > CpvAccess(HiWaterMark)) {
1827     CpvAccess(HiWaterMark) = CpvAccess(MemoryUsage);
1828   }
1829   if (CpvAccess(MemoryUsage) > 1.1 * CpvAccess(ReportedHiWaterMark)) {
1830     CmiPrintf("HIMEM STAT PE%d: %d Allocs, %d blocks, %lu K, Max %lu K\n",
1831             CmiMyPe(), CpvAccess(AllocCount), CpvAccess(BlocksAllocated),
1832             CpvAccess(MemoryUsage)/1024, CpvAccess(HiWaterMark)/1024);
1833     CpvAccess(ReportedHiWaterMark) = CpvAccess(MemoryUsage);
1834   }
1835   if ((CpvAccess(AllocCount) % 1000) == 0) {
1836     CmiPrintf("MEM STAT PE%d: %d Allocs, %d blocks, %lu K, Max %lu K\n",
1837             CmiMyPe(), CpvAccess(AllocCount), CpvAccess(BlocksAllocated),
1838             CpvAccess(MemoryUsage)/1024, CpvAccess(HiWaterMark)/1024);
1839   }
1840 #endif
1841
1842   res+=sizeof(CmiChunkHeader);
1843   SIZEFIELD(res)=size;
1844   REFFIELD(res)=1;
1845   return (void *)res;
1846 }
1847
1848 /** Follow the header links out to the most enclosing block */
1849 static void *CmiAllocFindEnclosing(void *blk) {
1850   int refCount = REFFIELD(blk);
1851   while (refCount < 0) {
1852     blk = (void *)((char*)blk+refCount); /* Jump to enclosing block */
1853     refCount = REFFIELD(blk);
1854   }
1855   return blk;
1856 }
1857
1858 /** Increment the reference count for this block's owner.
1859     This call must be matched by an equivalent CmiFree. */
1860 void CmiReference(void *blk)
1861 {
1862   REFFIELD(CmiAllocFindEnclosing(blk))++;
1863 }
1864
1865 /** Return the size of the user portion of this block. */
1866 int CmiSize(void *blk)
1867 {
1868   return SIZEFIELD(blk);
1869 }
1870
1871 /** Decrement the reference count for this block. */
1872 void CmiFree(void *blk)
1873 {
1874   void *parentBlk=CmiAllocFindEnclosing(blk);
1875   int refCount=REFFIELD(parentBlk);
1876 #ifndef CMK_OPTIMIZE
1877   if(refCount==0) /* Logic error: reference count shouldn't already have been zero */
1878     CmiAbort("CmiFree reference count was zero-- is this a duplicate free?");
1879 #endif
1880   refCount--;
1881   REFFIELD(parentBlk) = refCount;
1882   if(refCount==0) { /* This was the last reference to the block-- free it */
1883 #ifdef MEMMONITOR
1884     int size=SIZEFIELD(parentBlk);
1885     if (size > 1000000000) /* Absurdly large size field-- warning */
1886       CmiPrintf("MEMSTAT Uh-oh -- SIZEFIELD=%d\n",size);
1887     CpvAccess(MemoryUsage) -= (size + sizeof(CmiChunkHeader);
1888     CpvAccess(BlocksAllocated)--;
1889 #endif
1890
1891 #if CONVERSE_VERSION_ELAN
1892     elan_CmiFree(BLKSTART(parentBlk));
1893 #elif CONVERSE_VERSION_VMI
1894     CMI_VMI_CmiFree(BLKSTART(parentBlk));
1895 #elif CONVERSE_POOL
1896     CmiPoolFree(BLKSTART(parentBlk));
1897 #else
1898     free_nomigrate(BLKSTART(parentBlk));
1899 #endif
1900   }
1901 }
1902
1903
1904 /***************************************************************************
1905  *
1906  * Temporary-memory Allocation routines 
1907  *
1908  *  This buffer augments the storage available on the regular machine stack
1909  * for fairly large temporary buffers, which allows us to use smaller machine
1910  * stacks.
1911  *
1912  ***************************************************************************/
1913
1914 #define CMI_TMP_BUF_MAX 128*1024 /* Allow this much temporary storage. */
1915
1916 typedef struct {
1917   char *buf; /* Start of temporary buffer */
1918   int cur; /* First unused location in temporary buffer */
1919   int max; /* Length of temporary buffer */
1920 } CmiTmpBuf_t;
1921 CpvDeclare(CmiTmpBuf_t,CmiTmpBuf); /* One temporary buffer per PE */
1922
1923 static void CmiTmpSetup(CmiTmpBuf_t *b) {
1924   b->buf=malloc(CMI_TMP_BUF_MAX);
1925   b->cur=0;
1926   b->max=CMI_TMP_BUF_MAX;
1927 }
1928
1929 void *CmiTmpAlloc(int size) {
1930   if (!CpvInitialized(CmiTmpBuf)) {
1931     return malloc(size);
1932   }
1933   else { /* regular case */
1934     CmiTmpBuf_t *b=&CpvAccess(CmiTmpBuf);
1935     void *t;
1936     if (b->cur+size>b->max) {
1937       if (b->max==0) /* We're just uninitialized */
1938         CmiTmpSetup(b);
1939       else /* We're really out of space! */
1940         CmiAbort("CmiTmpAlloc: asked for too much temporary buffer space");
1941     }
1942     t=b->buf+b->cur;
1943     b->cur+=size;
1944     return t;
1945   }
1946 }
1947 void CmiTmpFree(void *t) {
1948   if (!CpvInitialized(CmiTmpBuf)) {
1949     free(t);
1950   }
1951   else { /* regular case */
1952     CmiTmpBuf_t *b=&CpvAccess(CmiTmpBuf);
1953     /* t should point into our temporary buffer: figure out where */
1954     int cur=((const char *)t)-b->buf;
1955 #ifndef CMK_OPTIMIZE
1956     if (cur<0 || cur>b->max)
1957       CmiAbort("CmiTmpFree: called with an invalid pointer");
1958 #endif
1959     b->cur=cur;
1960   }
1961 }
1962
1963 void CmiTmpInit(char **argv) {
1964   CpvInitialize(CmiTmpBuf_t,CmiTmpBuf);
1965   /* Set up this processor's temporary buffer */
1966   CmiTmpSetup(&CpvAccess(CmiTmpBuf));
1967 }
1968
1969 /******************************************************************************
1970
1971   Cross-platform directory creation
1972
1973   ****************************************************************************/
1974 #ifdef _MSC_VER
1975 /* Windows directory creation: */
1976 #include <windows.h>
1977
1978 void CmiMkdir(const char *dirName) {
1979         CreateDirectory(dirName,NULL);
1980 }
1981
1982 #else /* !_MSC_VER */
1983 /* UNIX directory creation */
1984 #include <unistd.h> 
1985 #include <sys/stat.h> /* from "mkdir" man page */
1986 #include <sys/types.h>
1987
1988 void CmiMkdir(const char *dirName) {
1989         mkdir(dirName,0777);
1990 }
1991
1992 #endif
1993
1994
1995 /******************************************************************************
1996
1997   Multiple Send function                               
1998
1999   ****************************************************************************/
2000
2001 CpvDeclare(int, CmiMainHandlerIDP); /* Main handler that is run on every node */
2002
2003 /****************************************************************************
2004 * DESCRIPTION : This function call allows the user to send multiple messages
2005 *               from one processor to another, all intended for differnet 
2006 *               handlers.
2007 *
2008 *               Parameters :
2009 *
2010 *               destPE, len, int sizes[0..len-1], char *messages[0..len-1]
2011 *
2012 ****************************************************************************/
2013 /* Round up message size to the message granularity. 
2014    Does this by adding, then truncating.
2015 */
2016 static int roundUpSize(unsigned int s) {
2017   return (int)((s+sizeof(double)-1)&~(sizeof(double)-1));
2018 }
2019 /* Return the amount of message padding required for a message
2020    with this many user bytes. 
2021  */
2022 static int paddingSize(unsigned int s) {
2023   return roundUpSize(s)-s;
2024 }
2025
2026 /* Message header for a bundle of multiple-sent messages */
2027 typedef struct {
2028   char convHeader[CmiMsgHeaderSizeBytes];
2029   int nMessages; /* Number of distinct messages bundled below. */
2030   double pad; /* To align the first message, which follows this header */
2031 } CmiMultipleSendHeader;
2032
2033 void _CmiMultipleSend(unsigned int destPE, int len, int sizes[], char *msgComps[], int immed)
2034 {
2035   CmiMultipleSendHeader header;
2036   int m; /* Outgoing message */
2037   CmiChunkHeader *msgHdr; /* Chunk headers for each message */
2038   double pad = 0; /* padding required */
2039   int vecLen; /* Number of pieces in outgoing message vector */
2040   int *vecSizes; /* Sizes of each piece we're sending out. */
2041   char **vecPtrs; /* Pointers to each piece we're sending out. */
2042   int vec; /* Entry we're currently filling out in above array */
2043
2044   msgHdr = (CmiChunkHeader *)CmiTmpAlloc(len * sizeof(CmiChunkHeader));
2045   /* Allocate memory for the outgoing vector*/
2046   vecLen=1+3*len; /* Header and 3 parts per message */
2047   vecSizes = (int *)CmiTmpAlloc(vecLen * sizeof(int));
2048   vecPtrs = (char **)CmiTmpAlloc(vecLen * sizeof(char *));
2049   vec=0;
2050   
2051   /* Build the header */
2052   header.nMessages=len;
2053   CmiSetHandler(&header, CpvAccess(CmiMainHandlerIDP));
2054 #if CMK_IMMEDIATE_MSG
2055   if (immed) CmiBecomeImmediate(&header);
2056 #endif
2057   vecSizes[vec]=sizeof(header); vecPtrs[vec]=(char *)&header;
2058   vec++;
2059
2060   /* Build an entry for each message: 
2061          | CmiChunkHeader | Message data | Message padding | ...next message entry ...
2062   */
2063   for (m=0;m<len;m++) {
2064     msgHdr[m].size=roundUpSize(sizes[m]); /* Size of message and padding */
2065     msgHdr[m].ref=0; /* Reference count will be filled out on receive side */
2066     
2067     /* First send the message's CmiChunkHeader (for use on receive side) */
2068     vecSizes[vec]=sizeof(CmiChunkHeader); vecPtrs[vec]=(char *)&msgHdr[m];
2069     vec++;
2070     
2071     /* Now send the actual message data */
2072     vecSizes[vec]=sizes[m]; vecPtrs[vec]=msgComps[m];
2073     vec++;
2074     
2075     /* Now send padding to align the next message on a double-boundary */
2076     vecSizes[vec]=paddingSize(sizes[m]); vecPtrs[vec]=(char *)&pad;
2077     vec++;
2078   }
2079   CmiAssert(vec==vecLen);
2080   
2081   CmiSyncVectorSend(destPE, vecLen, vecSizes, vecPtrs);
2082   
2083   CmiTmpFree(vecPtrs); /* CmiTmp: Be sure to throw away in opposite order of allocation */
2084   CmiTmpFree(vecSizes);
2085   CmiTmpFree(msgHdr);
2086 }
2087
2088 void CmiMultipleSend(unsigned int destPE, int len, int sizes[], char *msgComps[])
2089 {
2090   _CmiMultipleSend(destPE, len, sizes, msgComps, 0);
2091 }
2092
2093 void CmiMultipleIsend(unsigned int destPE, int len, int sizes[], char *msgComps[])
2094 {
2095   _CmiMultipleSend(destPE, len, sizes, msgComps, 1);
2096 }
2097
2098 /****************************************************************************
2099 * DESCRIPTION : This function initializes the main handler required for the
2100 *               CmiMultipleSend() function to work. 
2101 *               
2102 *               This function should be called once in any Converse program
2103 *               that uses CmiMultipleSend()
2104 *
2105 ****************************************************************************/
2106
2107 static void CmiMultiMsgHandler(char *msgWhole);
2108
2109 void CmiInitMultipleSend(void)
2110 {
2111   CpvInitialize(int,CmiMainHandlerIDP); 
2112   CpvAccess(CmiMainHandlerIDP) =
2113     CmiRegisterHandler((CmiHandler)CmiMultiMsgHandler);
2114 }
2115
2116 /****************************************************************************
2117 * DESCRIPTION : This function is the main handler that splits up the messages
2118 *               CmiMultipleSend() pastes together. 
2119 *
2120 ****************************************************************************/
2121
2122 static void CmiMultiMsgHandler(char *msgWhole)
2123 {
2124   int len=((CmiMultipleSendHeader *)msgWhole)->nMessages;
2125   int offset=sizeof(CmiMultipleSendHeader);
2126   int m;
2127   for (m=0;m<len;m++) {
2128     CmiChunkHeader *ch=(CmiChunkHeader *)(msgWhole+offset);
2129     char *msg=(msgWhole+offset+sizeof(CmiChunkHeader));
2130     int msgSize=ch->size; /* Size of user portion of message (plus padding at end) */
2131     /* Link new message to owner via a negative ref pointer */
2132     ch->ref=msgWhole-msg; 
2133     CmiReference(msg); /* Follows link & increases reference count of *msgWhole* */
2134     CmiSyncSendAndFree(CmiMyPe(), msgSize, msg);
2135     offset+= sizeof(CmiChunkHeader) + msgSize;
2136   }
2137   /* Release our reference to the whole message.  The message will
2138      only actually be deleted once all its sub-messages are free'd as well. */
2139   CmiFree(msgWhole);
2140 }
2141
2142 /****************************************************************************
2143 * Hypercube broadcast message passing.
2144 ****************************************************************************/
2145
2146 int HypercubeGetBcastDestinations(int mype, int total_pes, int k, int *dest_pes) {
2147   int num_pes = 0;
2148   for ( ; k>=0; --k) {
2149     /* add the processor destination at level k if it exist */
2150     dest_pes[num_pes] = mype ^ (1<<k);
2151     if (dest_pes[num_pes] >= total_pes) {
2152       /* find the first proc in the other part of the current dimention */
2153       dest_pes[num_pes] &= (-1)<<k;
2154       /* if the first proc there is over CmiNumPes() then there is no other
2155          dimension, otherwise if it is valid compute my correspondent in such
2156          a way to minimize the load for every processor */
2157       if (total_pes>dest_pes[num_pes]) dest_pes[num_pes] += (mype - (mype & ((-1)<<k))) % (total_pes - dest_pes[num_pes]);
2158       }
2159     if (dest_pes[num_pes] < total_pes) {
2160       /* if the destination is in the acceptable range increment num_pes */
2161       ++num_pes;
2162     }
2163   }
2164   return num_pes;
2165 }
2166
2167
2168 /****************************************************************************
2169 * DESCRIPTION : This function initializes the main handler required for the
2170 *               Immediate message
2171 *               
2172 *               This function should be called once in any Converse program
2173 *
2174 ****************************************************************************/
2175
2176 int _immediateLock = 0; /* if locked, all immediate message handling will be delayed. */
2177 int _immediateFlag = 0; /* if set, there is delayed immediate message. */
2178
2179 CpvDeclare(int, CmiImmediateMsgHandlerIdx); /* Main handler that is run on every node */
2180
2181 /* xdl is the real handler */
2182 static void CmiImmediateMsgHandler(char *msg)
2183 {
2184   CmiSetHandler(msg, CmiGetXHandler(msg));
2185   CmiHandleMessage(msg);
2186 }
2187
2188 void CmiInitImmediateMsg(void)
2189 {
2190   CpvInitialize(int,CmiImmediateMsgHandlerIdx); 
2191   CpvAccess(CmiImmediateMsgHandlerIdx) =
2192     CmiRegisterHandler((CmiHandler)CmiImmediateMsgHandler);
2193 }
2194
2195 #if !CMK_IMMEDIATE_MSG
2196 #if !CMK_MACHINE_PROGRESS_DEFINED
2197 void CmiProbeImmediateMsg()
2198 {
2199 }
2200 #endif
2201 #endif 
2202
2203 /******** Idle timeout module (+idletimeout=30) *********/
2204
2205 typedef struct {
2206   int idle_timeout;/*Milliseconds to wait idle before aborting*/
2207   int is_idle;/*Boolean currently-idle flag*/
2208   int call_count;/*Number of timeout calls currently in flight*/
2209 } cmi_cpu_idlerec;
2210
2211 static void on_timeout(cmi_cpu_idlerec *rec,double curWallTime)
2212 {
2213   rec->call_count--;
2214   if(rec->call_count==0 && rec->is_idle==1) {
2215     CmiError("Idle time on PE %d exceeded specified timeout.\n", CmiMyPe());
2216     CmiAbort("Exiting.\n");
2217   }
2218 }
2219 static void on_idle(cmi_cpu_idlerec *rec,double curWallTime)
2220 {
2221   CcdCallFnAfter((CcdVoidFn)on_timeout, rec, rec->idle_timeout);
2222   rec->call_count++; /*Keeps track of overlapping timeout calls.*/  
2223   rec->is_idle = 1;
2224 }
2225 static void on_busy(cmi_cpu_idlerec *rec,double curWallTime)
2226 {
2227   rec->is_idle = 0;
2228 }
2229 static void CIdleTimeoutInit(char **argv)
2230 {
2231   int idle_timeout=0; /*Seconds to wait*/
2232   CmiGetArgIntDesc(argv,"+idle-timeout",&idle_timeout,"Abort if idle for this many seconds");
2233   if(idle_timeout != 0) {
2234     cmi_cpu_idlerec *rec=(cmi_cpu_idlerec *)malloc(sizeof(cmi_cpu_idlerec));
2235     _MEMCHECK(rec);
2236     rec->idle_timeout=idle_timeout*1000;
2237     rec->is_idle=0;
2238     rec->call_count=0;
2239     CcdCallOnCondition(CcdPROCESSOR_BEGIN_IDLE, (CcdVoidFn)on_idle, rec);
2240     CcdCallOnCondition(CcdPROCESSOR_BEGIN_BUSY, (CcdVoidFn)on_busy, rec);
2241   }
2242 }
2243
2244 /*****************************************************************************
2245  *
2246  * Converse Initialization
2247  *
2248  *****************************************************************************/
2249
2250 extern void CrnInit(void);
2251 extern void CmiIsomallocInit(char **argv);
2252
2253 static void CmiProcessPriority(char **argv)
2254 {
2255   int dummy, nicelevel=-100;      /* process priority */
2256   CmiGetArgIntDesc(argv,"+nice",&nicelevel,"Set the process priority level");
2257   /* ignore others */
2258   while (CmiGetArgIntDesc(argv,"+nice",&dummy,"Set the process priority level"));
2259   /* call setpriority once on each process to set process's priority */
2260   if (CmiMyRank() == 0 && nicelevel != -100)  {
2261 #ifndef _WIN32
2262     if (0!=setpriority(PRIO_PROCESS, 0, nicelevel))  {
2263       CmiPrintf("[%d] setpriority failed with value %d. \n", CmiMyPe(), nicelevel);
2264       perror("setpriority");
2265       CmiAbort("setpriority failed.");
2266     }
2267     else
2268       CmiPrintf("[%d] Charm++: setpriority %d\n", CmiMyPe(), nicelevel);
2269 #else
2270     HANDLE hProcess = GetCurrentProcess();
2271     DWORD dwPriorityClass = NORMAL_PRIORITY_CLASS;
2272     char *prio_str = "NORMAL_PRIORITY_CLASS";
2273     BOOL status;
2274     /*
2275        <-20:      real time
2276        -20--10:   high 
2277        -10-0:     above normal
2278        0:         normal
2279        0-10:      below normal
2280        10-:       idle
2281     */
2282     if (0) ;
2283 #ifdef BELOW_NORMAL_PRIORITY_CLASS
2284     else if (nicelevel<10 && nicelevel>0) {
2285       dwPriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
2286       prio_str = "BELOW_NORMAL_PRIORITY_CLASS";
2287     }
2288 #endif
2289     else if (nicelevel>0) {
2290       dwPriorityClass = IDLE_PRIORITY_CLASS;
2291       prio_str = "IDLE_PRIORITY_CLASS";
2292     }
2293     else if (nicelevel<=-20) {
2294       dwPriorityClass = REALTIME_PRIORITY_CLASS;
2295       prio_str = "REALTIME_PRIORITY_CLASS";
2296     }
2297 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
2298     else if (nicelevel>-10 && nicelevel<0) {
2299       dwPriorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
2300       prio_str = "ABOVE_NORMAL_PRIORITY_CLASS";
2301     }
2302 #endif
2303     else if (nicelevel<0) {
2304       dwPriorityClass = HIGH_PRIORITY_CLASS;
2305       prio_str = "HIGH_PRIORITY_CLASS";
2306     }
2307     status = SetPriorityClass(hProcess, dwPriorityClass);
2308     if (!status)  {
2309         int err=GetLastError();
2310         CmiPrintf("SetPriorityClass failed errno=%d, WSAerr=%d\n",errno, err);
2311         CmiAbort("SetPriorityClass failed.");
2312     }
2313     else
2314       CmiPrintf("[%d] Charm++: setpriority %s\n", CmiMyPe(), prio_str);
2315 #endif
2316   }
2317 }
2318
2319 void CommunicationServerInit()
2320 {
2321 #if CMK_IMMEDIATE_MSG
2322   CQdCpvInit();
2323   CpvInitialize(int,CmiImmediateMsgHandlerIdx); 
2324 #endif
2325 }
2326
2327 /**
2328   Main Converse initialization routine.  This routine is 
2329   called by the machine file (machine.c) to set up Converse.
2330   It's "Common" because it's shared by all the machine.c files. 
2331   
2332   The main task of this routine is to set up all the Cpv's
2333   (message queues, handler tables, etc.) used during main execution.
2334   
2335   On SMP versions, this initialization routine is called by 
2336   *all* processors of a node simultaniously.  It's *also* called
2337   by the communication thread, which is rather strange but needed
2338   for immediate messages.  Each call to this routine expects a 
2339   different copy of the argv arguments, so use CmiCopyArgs(argv).
2340   
2341   Requires:
2342     - A working network layer.
2343     - Working Cpv's and CmiNodeBarrier.
2344     - CthInit to already have been called.  CthInit is called
2345       from the machine layer directly, because some machine layers
2346       (like uth) use Converse threads internally.
2347
2348   Initialization is somewhat subtle, in that various modules
2349   won't work properly until they're initialized.  For example,
2350   nobody can register handlers before calling CmiHandlerInit.
2351 */
2352 void ConverseCommonInit(char **argv)
2353 {
2354   CmiArgInit(argv);
2355   CmiMemoryInit(argv);
2356 #if CONVERSE_POOL
2357   CmiPoolAllocInit(30);  
2358 #endif
2359   CmiTmpInit(argv);
2360   CmiTimerInit();
2361   CstatsInit(argv);
2362
2363   CcdModuleInit(argv);
2364   CmiHandlerInit();
2365   CIdleTimeoutInit(argv);
2366   
2367 #ifndef CMK_OPTIMIZE
2368   traceInit(argv);
2369 /*initTraceCore(argv);*/ /* projector */
2370 #endif
2371   CmiProcessPriority(argv);
2372
2373 #if CMK_CCS_AVAILABLE
2374   CcsInit(argv);
2375 #endif
2376   CmiPersistentInit();
2377   CmiIsomallocInit(argv);
2378   CpdInit();
2379   CmiDeliversInit();
2380   CsdInit(argv);
2381   CthSchedInit();
2382   CmiGroupInit();
2383   CmiMulticastInit();
2384   CmiInitMultipleSend();
2385   CQdInit();
2386
2387   CrnInit();
2388   CmiInitImmediateMsg();
2389   CldModuleInit(argv);
2390   
2391   /* main thread is suspendable */
2392 /*
2393   CthSetSuspendable(CthSelf(), 0);
2394 */
2395 }
2396
2397 void ConverseCommonExit(void)
2398 {
2399   CcsImpl_kill();
2400
2401 #ifndef CMK_OPTIMIZE
2402   traceClose();
2403 /*closeTraceCore();*/ /* projector */
2404 #endif
2405
2406 }
2407
2408 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
2409
2410 void CmiPrintf(const char *format, ...)
2411 {
2412   va_list args;
2413   va_start(args,format);
2414   vprintf(format, args);
2415   fflush(stdout);
2416   va_end(args);
2417 }
2418
2419 void CmiError(const char *format, ...)
2420 {
2421   va_list args;
2422   va_start(args,format);
2423   vfprintf(stderr,format, args);
2424   fflush(stderr);
2425   va_end(args);
2426 }
2427
2428 #endif
2429
2430 void __cmi_assert(const char *expr, const char *file, int line)
2431 {
2432   CmiError("[%d] Assertion \"%s\" failed in file %s line %d.\n",
2433       CmiMyPe(), expr, file, line);
2434   CmiAbort("");
2435 }
2436
2437 char *CmiCopyMsg(char *msg, int len)
2438 {
2439   char *copy = (char *)CmiAlloc(len);
2440   _MEMCHECK(copy);
2441   memcpy(copy, msg, len);
2442   return copy;
2443 }
2444
2445 unsigned char computeCheckSum(unsigned char *data, int len)
2446 {
2447   int i;
2448   unsigned char ret = 0;
2449   for (i=0; i<len; i++) ret ^= (unsigned char)data[i];
2450   return ret;
2451 }
2452
2453 /*@}*/