00001
00052 #include <stdio.h>
00053 #include <stdlib.h>
00054 #include <string.h>
00055 #include "hrctimer.h"
00056 #ifndef __STDC_FORMAT_MACROS
00057 # define __STDC_FORMAT_MACROS
00058 #endif
00059 #ifndef __STDC_LIMIT_MACROS
00060 # define __STDC_LIMIT_MACROS
00061 #endif
00062 #include <inttypes.h>
00063 #include <errno.h>
00064 #ifndef _WIN32
00065 #include <sys/time.h>
00066 #include <sys/resource.h>
00067 #else
00068 #define snprintf _snprintf
00069 #endif
00070
00071 #include "converse.h"
00072 #include "conv-trace.h"
00073 #include "sockRoutines.h"
00074 #include "queueing.h"
00075 #if CMK_SMP && CMK_TASKQUEUE
00076 #include "taskqueue.h"
00077 #include "conv-taskQ.h"
00078 #endif
00079 #include "conv-ccs.h"
00080 #include "ccs-server.h"
00081 #include "memory-isomalloc.h"
00082 #if CMK_PROJECTOR
00083 #include "converseEvents.h"
00084 #include "traceCoreCommon.h"
00085 #include "machineEvents.h"
00086 #endif
00087
00088 extern const char * const CmiCommitID;
00089
00090 #if CMI_QD
00091 void initQd(char **argv);
00092 #endif
00093
00094 #if CMK_OUT_OF_CORE
00095 #include "conv-ooc.h"
00096 #endif
00097
00098 #if CONVERSE_POOL
00099 #include "cmipool.h"
00100 #else
00101 void CmiPoolAllocInit(int numBins);
00102 #endif
00103
00104 #if CMK_CONDS_USE_SPECIAL_CODE
00105 CmiSwitchToPEFnPtr CmiSwitchToPE;
00106 #endif
00107
00108 CpvExtern(int, _traceCoreOn);
00109 void CcdModuleInit(char **);
00110 void CmiMemoryInit(char **);
00111 void CldModuleInit(char **);
00112
00113 #if CMK_WHEN_PROCESSOR_IDLE_USLEEP
00114 #include <sys/types.h>
00115 #include <sys/time.h>
00116 #endif
00117
00118 #if CMK_TIMER_USE_TIMES
00119 #include <sys/times.h>
00120 #include <limits.h>
00121 #include <unistd.h>
00122 #endif
00123
00124 #if CMK_TIMER_USE_GETRUSAGE
00125 #include <sys/time.h>
00126 #include <sys/resource.h>
00127 #endif
00128
00129 #if CMK_TIMER_USE_RDTSC
00130 #include <string.h>
00131 #include <unistd.h>
00132 #include <time.h>
00133 #include <stdio.h>
00134 #include <sys/time.h>
00135 #include <sys/resource.h>
00136 #endif
00137
00138 #ifdef CMK_TIMER_USE_WIN32API
00139 #include <stdlib.h>
00140 #include <time.h>
00141 #include <sys/types.h>
00142 #include <sys/timeb.h>
00143 #endif
00144
00145 #ifdef CMK_HAS_ASCTIME
00146 #include <time.h>
00147 #endif
00148
00149 #include "quiescence.h"
00150
00151 #if USE_MPI_CTRLMSG_SCHEME && CMK_CONVERSE_MPI
00152 #include <mpi.h>
00153 #endif
00154
00155 #if CMK_TRACE_ENABLED
00156 struct envelope;
00157 void traceAddThreadListeners(CthThread tid, struct envelope *env);
00158 #endif
00159
00160 void seedBalancerExit(void);
00161 void EmergencyExit(void);
00162
00163
00164 CpvDeclare(int,_curRestartPhase);
00165 static int CsdLocalMax = CSD_LOCAL_MAX_DEFAULT;
00166
00167 int CharmLibInterOperate = 0;
00168 CpvCExtern(int,interopExitFlag);
00169 CpvDeclare(int,interopExitFlag);
00170
00171 CpvStaticDeclare(int, CmiMainHandlerIDP);
00172
00173 #if CMK_MEM_CHECKPOINT
00174 void (*notify_crash_fn)(int) = NULL;
00175 #endif
00176
00177 CpvDeclare(char *, _validProcessors);
00178
00179 #if CMK_CUDA
00180 CpvExtern(int, n_hapi_events);
00181 extern "C" void hapiPollEvents();
00182 extern "C" void exitHybridAPI();
00183 #endif
00184
00185
00186
00187
00188
00189
00190
00191 #ifdef MEMMONITOR
00192 typedef unsigned long mmulong;
00193 CpvDeclare(mmulong,MemoryUsage);
00194 CpvDeclare(mmulong,HiWaterMark);
00195 CpvDeclare(mmulong,ReportedHiWaterMark);
00196 CpvDeclare(int,AllocCount);
00197 CpvDeclare(int,BlocksAllocated);
00198 #endif
00199
00200 #define MAX_HANDLERS 512
00201
00202 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
00203 CpvDeclare(int,expIOFlushFlag);
00204 #if CMI_IO_BUFFER_EXPLICIT
00205
00206 #define DEFAULT_IO_BUFFER_SIZE 250000
00207 CpvDeclare(char*,explicitIOBuffer);
00208 CpvDeclare(int,expIOBufferSize);
00209 #endif
00210 #endif
00211
00212 #if CMK_NODE_QUEUE_AVAILABLE
00213 void *CmiGetNonLocalNodeQ();
00214 #endif
00215
00216 CpvDeclare(Queue, CsdSchedQueue);
00217
00218 #if CMK_OUT_OF_CORE
00219
00220 CpvDeclare(Queue, CsdPrefetchQueue);
00221 pthread_mutex_t prefetchLock;
00222 #endif
00223
00224 #if CMK_NODE_QUEUE_AVAILABLE
00225 CsvDeclare(Queue, CsdNodeQueue);
00226 CsvDeclare(CmiNodeLock, CsdNodeQueueLock);
00227 #endif
00228 CpvDeclare(int, CsdStopFlag);
00229 CpvDeclare(int, CsdLocalCounter);
00230
00231 CpvDeclare(int, _urgentSend);
00232
00233 CmiNodeLock _smp_mutex;
00234
00235 #if CMK_USE_IBVERBS | CMK_USE_IBUD
00236 void *infi_CmiAlloc(int size);
00237 void infi_CmiFree(void *ptr);
00238 void infi_freeMultipleSend(void *ptr);
00239 void infi_unregAndFreeMeta(void *ch);
00240 #endif
00241
00242 #if CMK_SMP && CMK_BLUEGENEQ && SPECIFIC_PCQUEUE
00243 void * CmiAlloc_bgq (int size);
00244 void CmiFree_bgq (void * buf);
00245 #endif
00246
00247 #if CMK_SMP && CMK_PPC_ATOMIC_QUEUE
00248 void * CmiAlloc_ppcq (int size);
00249 void CmiFree_ppcq (void * buf);
00250 #endif
00251
00252 #if CMK_GRID_QUEUE_AVAILABLE
00253 CpvDeclare(void *, CkGridObject);
00254 CpvDeclare(Queue, CsdGridQueue);
00255 #endif
00256
00257 #if CMK_CRAYXE || CMK_CRAYXC || CMK_OFI
00258 void* LrtsAlloc(int, int);
00259 void* LrtsRdmaAlloc(int, int);
00260 void LrtsFree(void*);
00261 void LrtsRdmaFree(void*);
00262 #endif
00263
00264 CpvStaticDeclare(int, cmiMyPeIdle);
00265 #if CMK_SMP && CMK_TASKQUEUE
00266 CsvDeclare(unsigned int, idleThreadsCnt);
00267 CpvDeclare(Queue, CsdTaskQueue);
00268 CpvDeclare(void *, CmiSuspendedTaskQueue);
00269 #endif
00270
00271 CpvDeclare(int, isHelperOn);
00272
00273 extern int CmiMyLocalRank;
00274 int CmiMyLocalRank;
00275
00276 #if CMK_LOCKLESS_QUEUE
00277
00278
00279
00280
00281
00282 int DataNodeSize;
00283 int MaxDataNodes;
00284 int QueueUpperBound;
00285 int DataNodeWrap;
00286 int QueueWrap;
00287 int messageQueueOverflow;
00288 #endif
00289
00290
00291
00292
00293
00294
00295
00296 static int usageChecked=0;
00297 static int printUsage=0;
00298 static const char *CLAformatString="%20s %10s %s\n";
00299
00304 typedef struct {
00305 const char *arg;
00306 const char *param;
00307 const char *desc;
00308 } CLA;
00309 static int CLAlistLen=0;
00310 static int CLAlistMax=0;
00311 static CLA *CLAlist=NULL;
00312
00314 static void CmiAddCLA(const char *arg,const char *param,const char *desc) {
00315 int i;
00316 if (CmiMyPe()!=0) return;
00317 if (desc==NULL) return;
00318 if (usageChecked) {
00319 if (printUsage)
00320 CmiPrintf(CLAformatString,arg,param,desc);
00321 }
00322 else {
00323
00324
00325 CLA *temp;
00326 i=CLAlistLen++;
00327 if (CLAlistLen>CLAlistMax) {
00328 CLAlistMax=16+2*CLAlistLen;
00329 temp = (CLA *)realloc(CLAlist,sizeof(CLA)*CLAlistMax);
00330 if(temp != NULL) {
00331 CLAlist=temp;
00332 } else {
00333 free(CLAlist);
00334 CmiAbort("Reallocation failed for CLAlist\n");
00335 }
00336 }
00337 CLAlist[i].arg=arg;
00338 CLAlist[i].param=param;
00339 CLAlist[i].desc=desc;
00340 }
00341 }
00342
00344 static void CmiPrintCLAs(void) {
00345 int i;
00346 if (CmiMyPe()!=0) return;
00347 CmiPrintf("Converse Machine Command-line Parameters:\n ");
00348 CmiPrintf(CLAformatString,"Option:","Parameter:","Description:");
00349 for (i=0;i<CLAlistLen;i++) {
00350 CLA *c=&CLAlist[i];
00351 CmiPrintf(CLAformatString,c->arg,c->param,c->desc);
00352 }
00353 }
00354
00360 void CmiArgInit(char **argv) {
00361 int i;
00362 CmiLock(_smp_mutex);
00363 for (i=0;argv[i]!=NULL;i++)
00364 {
00365 if (0==strcmp(argv[i],"-?") ||
00366 0==strcmp(argv[i],"-h") ||
00367 0==strcmp(argv[i],"--help"))
00368 {
00369 printUsage=1;
00370
00371
00372 CmiPrintCLAs();
00373 }
00374 }
00375 if (CmiMyPe()==0) {
00376 CLAlistLen=CLAlistMax=0;
00377 free(CLAlist); CLAlist=NULL;
00378 }
00379 usageChecked=1;
00380 CmiUnlock(_smp_mutex);
00381 }
00382
00384 int CmiArgGivingUsage(void) {
00385 return (CmiMyPe()==0) && printUsage;
00386 }
00387
00389 void CmiArgGroup(const char *parentName,const char *groupName) {
00390 if (CmiArgGivingUsage()) {
00391 if (groupName==NULL) groupName=parentName;
00392 CmiPrintf("\n%s Command-line Parameters:\n",groupName);
00393 }
00394 }
00395
00397 int CmiGetArgc(char **argv)
00398 {
00399 int i=0,argc=0;
00400 if (argv)
00401 while (argv[i++]!=NULL)
00402 argc++;
00403 return argc;
00404 }
00405
00407 char **CmiCopyArgs(char **argv)
00408 {
00409 int argc=CmiGetArgc(argv);
00410 char **ret=(char **)malloc(sizeof(char *)*(argc+1));
00411 int i;
00412 for (i=0;i<=argc;i++)
00413 ret[i]=argv[i];
00414 return ret;
00415 }
00416
00422 void CmiDeleteArgs(char **argv,int k)
00423 {
00424 int i=0;
00425 while ((argv[i]=argv[i+k])!=NULL)
00426 i++;
00427 }
00428
00436 int CmiGetArgStringDesc(char **argv,const char *arg,char **optDest,const char *desc)
00437 {
00438 int i;
00439 CmiAddCLA(arg,"string",desc);
00440 for (i=0;argv[i]!=NULL;i++)
00441 if (0==strcmp(argv[i],arg))
00442 {
00443 if (argv[i+1]==NULL) CmiAbort("Argument not complete!");
00444 *optDest=argv[i+1];
00445 CmiDeleteArgs(&argv[i],2);
00446 return 1;
00447 }
00448 return 0;
00449 }
00450 int CmiGetArgString(char **argv,const char *arg,char **optDest) {
00451 return CmiGetArgStringDesc(argv,arg,optDest,"");
00452 }
00453
00457 int CmiGetArgDoubleDesc(char **argv,const char *arg,double *optDest,const char *desc) {
00458 char *number=NULL;
00459 CmiAddCLA(arg,"number",desc);
00460 if (!CmiGetArgStringDesc(argv,arg,&number,NULL)) return 0;
00461 if (1!=sscanf(number,"%lg",optDest)) return 0;
00462 return 1;
00463 }
00464 int CmiGetArgDouble(char **argv,const char *arg,double *optDest) {
00465 return CmiGetArgDoubleDesc(argv,arg,optDest,"");
00466 }
00467
00475 int CmiGetArgIntDesc(char **argv,const char *arg,int *optDest,const char *desc)
00476 {
00477 int i;
00478 int argLen=strlen(arg);
00479 CmiAddCLA(arg,"integer",desc);
00480 for (i=0;argv[i]!=NULL;i++)
00481 if (0==strncmp(argv[i],arg,argLen))
00482 {
00483 const char *opt=NULL;
00484 int nDel=0;
00485 switch(argv[i][argLen]) {
00486 case 0:
00487 opt=argv[i+1]; nDel=2; break;
00488 case '=':
00489 opt=&argv[i][argLen+1]; nDel=1; break;
00490 case '-':case '+':
00491 case '0':case '1':case '2':case '3':case '4':
00492 case '5':case '6':case '7':case '8':case '9':
00493
00494 opt=&argv[i][argLen]; nDel=1; break;
00495 default:
00496 continue;
00497 }
00498 if (opt==NULL) {
00499 fprintf(stderr, "Command-line flag '%s' expects a numerical argument, "
00500 "but none was provided\n", arg);
00501 CmiAbort("Bad command-line argument\n");
00502 }
00503 if (sscanf(opt,"%i",optDest)<1) {
00504
00505 fprintf(stderr,"Cannot parse %s option '%s' "
00506 "as an integer.\n",arg,opt);
00507 CmiAbort("Bad command-line argument\n");
00508 }
00509 CmiDeleteArgs(&argv[i],nDel);
00510 return 1;
00511 }
00512 return 0;
00513 }
00514 int CmiGetArgInt(char **argv,const char *arg,int *optDest) {
00515 return CmiGetArgIntDesc(argv,arg,optDest,"");
00516 }
00517
00518 int CmiGetArgLongDesc(char **argv,const char *arg,CmiInt8 *optDest,const char *desc)
00519 {
00520 int i;
00521 int argLen=strlen(arg);
00522 CmiAddCLA(arg,"integer",desc);
00523 for (i=0;argv[i]!=NULL;i++)
00524 if (0==strncmp(argv[i],arg,argLen))
00525 {
00526 const char *opt=NULL;
00527 int nDel=0;
00528 switch(argv[i][argLen]) {
00529 case 0:
00530 opt=argv[i+1]; nDel=2; break;
00531 case '=':
00532 opt=&argv[i][argLen+1]; nDel=1; break;
00533 case '-':case '+':
00534 case '0':case '1':case '2':case '3':case '4':
00535 case '5':case '6':case '7':case '8':case '9':
00536
00537 opt=&argv[i][argLen]; nDel=1; break;
00538 default:
00539 continue;
00540 }
00541 if (opt==NULL) {
00542 fprintf(stderr, "Command-line flag '%s' expects a numerical argument, "
00543 "but none was provided\n", arg);
00544 CmiAbort("Bad command-line argument\n");
00545 }
00546 if (sscanf(opt,"%" SCNd64,optDest)<1) {
00547
00548 fprintf(stderr,"Cannot parse %s option '%s' "
00549 "as a long integer.\n",arg,opt);
00550 CmiAbort("Bad command-line argument\n");
00551 }
00552 CmiDeleteArgs(&argv[i],nDel);
00553 return 1;
00554 }
00555 return 0;
00556 }
00557 int CmiGetArgLong(char **argv,const char *arg,CmiInt8 *optDest) {
00558 return CmiGetArgLongDesc(argv,arg,optDest,"");
00559 }
00560
00566 int CmiGetArgFlagDesc(char **argv,const char *arg,const char *desc)
00567 {
00568 int i;
00569 CmiAddCLA(arg,"",desc);
00570 for (i=0;argv[i]!=NULL;i++)
00571 if (0==strcmp(argv[i],arg))
00572 {
00573 CmiDeleteArgs(&argv[i],1);
00574 return 1;
00575 }
00576 return 0;
00577 }
00578 int CmiGetArgFlag(char **argv,const char *arg) {
00579 return CmiGetArgFlagDesc(argv,arg,"");
00580 }
00581
00582 void CmiDeprecateArgInt(char **argv,const char *arg,const char *desc,const char *warning)
00583 {
00584 int dummy = 0, found = CmiGetArgIntDesc(argv, arg, &dummy, desc);
00585
00586 if (found)
00587 CmiPrintf(warning);
00588 }
00589
00590
00591
00592
00593
00594
00595 #include "cmibacktrace.C"
00596
00597
00598
00599
00600
00601
00602 static char *_implTrimParenthesis(char *str, int trimname) {
00603 char *lParen=str, *ret=NULL, *rParen=NULL;
00604 while (*lParen!='(') {
00605 if (*lParen==0) return str;
00606 lParen++;
00607 }
00608
00609 ret=lParen+1;
00610 rParen=ret;
00611 while (*rParen!=')') {
00612 if (*rParen==0) return ret;
00613 rParen++;
00614 }
00615
00616 *rParen=trimname?0:' ';
00617 return ret;
00618 }
00619
00620
00621
00622
00623
00624
00625 static const char* _implGetBacktraceSys(const char *name) {
00626 if (0==strncmp(name,"_call",5))
00627 {
00628 if (0==strncmp(name,"_call_",6)) return "Call Entry Method";
00629 if (0==strncmp(name,"_callthr_",9)) return "Call Threaded Entry Method";
00630 }
00631 if (0==strncmp(name,"CthResume",9)) return "Resumed thread";
00632 if (0==strncmp(name,"qt_args",7)) return "Converse thread";
00633
00634 return 0;
00635 }
00636
00638 void CmiBacktracePrint(void **retPtrs,int nLevels) {
00639 if (nLevels>0) {
00640 int i;
00641 char **names=CmiBacktraceLookup(retPtrs,nLevels);
00642 if (names==NULL) return;
00643 CmiPrintf("[%d] Stack Traceback:\n", CmiMyPe());
00644 for (i=0;i<nLevels;i++) {
00645 if (names[i] == NULL) continue;
00646 {
00647 const char *trimmed=_implTrimParenthesis(names[i], 0);
00648 const char *print=trimmed;
00649 const char *sys=_implGetBacktraceSys(print);
00650 if (sys) {
00651 CmiPrintf(" [%d] Charm++ Runtime: %s (%s)\n",i,sys,print);
00652 break;
00653 } else {
00654 CmiPrintf(" [%d:%d] %s\n",CmiMyPe(),i,print);
00655 }
00656 }
00657 }
00658 free(names);
00659 }
00660 }
00661
00662
00663
00664
00665 void CmiPrintStackTrace(int nSkip) {
00666 #if CMK_USE_BACKTRACE
00667 int nLevels=max_stack;
00668 void *stackPtrs[max_stack];
00669 CmiBacktraceRecord(stackPtrs,1+nSkip,&nLevels);
00670 CmiBacktracePrint(stackPtrs,nLevels);
00671 #endif
00672 }
00673
00674 int CmiIsFortranLibraryCall(void) {
00675 #if CMK_USE_BACKTRACE
00676 int ret = 0;
00677 int nLevels=9;
00678 void *stackPtrs[18];
00679 CmiBacktraceRecord(stackPtrs,1,&nLevels);
00680 if (nLevels>0) {
00681 int i;
00682 char **names=CmiBacktraceLookup(stackPtrs,nLevels);
00683 const char *trimmed;
00684 if (names==NULL) return 0;
00685 for (i=0;i<nLevels;i++) {
00686 if (names[i] == NULL) continue;
00687 trimmed=_implTrimParenthesis(names[i], 1);
00688 if (strncmp(trimmed, "for__", 5) == 0
00689 || strncmp(trimmed, "_xlf", 4) == 0
00690 || strncmp(trimmed, "_xlfBeginIO", 11) == 0
00691 || strncmp(trimmed, "_gfortran_", 10) == 0
00692 )
00693 {
00694 ret = 1; break; }
00695 }
00696 free(names);
00697 }
00698 return ret;
00699 #else
00700 return 0;
00701 #endif
00702 }
00703
00704
00705
00706
00707
00708
00709
00710 CpvDeclare(int, CstatsMaxChareQueueLength);
00711 CpvDeclare(int, CstatsMaxForChareQueueLength);
00712 CpvDeclare(int, CstatsMaxFixedChareQueueLength);
00713 CpvStaticDeclare(int, CstatPrintQueueStatsFlag);
00714 CpvStaticDeclare(int, CstatPrintMemStatsFlag);
00715
00716 void CstatsInit(char ** argv)
00717 {
00718
00719 #ifdef MEMMONITOR
00720 CpvInitialize(mmulong,MemoryUsage);
00721 CpvAccess(MemoryUsage) = 0;
00722 CpvInitialize(mmulong,HiWaterMark);
00723 CpvAccess(HiWaterMark) = 0;
00724 CpvInitialize(mmulong,ReportedHiWaterMark);
00725 CpvAccess(ReportedHiWaterMark) = 0;
00726 CpvInitialize(int,AllocCount);
00727 CpvAccess(AllocCount) = 0;
00728 CpvInitialize(int,BlocksAllocated);
00729 CpvAccess(BlocksAllocated) = 0;
00730 #endif
00731
00732 CpvInitialize(int, CstatsMaxChareQueueLength);
00733 CpvInitialize(int, CstatsMaxForChareQueueLength);
00734 CpvInitialize(int, CstatsMaxFixedChareQueueLength);
00735 CpvInitialize(int, CstatPrintQueueStatsFlag);
00736 CpvInitialize(int, CstatPrintMemStatsFlag);
00737
00738 CpvAccess(CstatsMaxChareQueueLength) = 0;
00739 CpvAccess(CstatsMaxForChareQueueLength) = 0;
00740 CpvAccess(CstatsMaxFixedChareQueueLength) = 0;
00741 CpvAccess(CstatPrintQueueStatsFlag) = 0;
00742 CpvAccess(CstatPrintMemStatsFlag) = 0;
00743
00744 #if 0
00745 if (CmiGetArgFlagDesc(argv,"+mems", "Print memory statistics at shutdown"))
00746 CpvAccess(CstatPrintMemStatsFlag)=1;
00747 if (CmiGetArgFlagDesc(argv,"+qs", "Print queue statistics at shutdown"))
00748 CpvAccess(CstatPrintQueueStatsFlag)=1;
00749 #endif
00750 }
00751
00752 int CstatMemory(int i)
00753 {
00754 return 0;
00755 }
00756
00757 int CstatPrintQueueStats(void)
00758 {
00759 return CpvAccess(CstatPrintQueueStatsFlag);
00760 }
00761
00762 int CstatPrintMemStats(void)
00763 {
00764 return CpvAccess(CstatPrintMemStatsFlag);
00765 }
00766
00767
00768
00769
00770
00771
00772
00773 CpvDeclare(CmiHandlerInfo*, CmiHandlerTable);
00774 CpvStaticDeclare(int , CmiHandlerCount);
00775 CpvStaticDeclare(int , CmiHandlerLocal);
00776 CpvStaticDeclare(int , CmiHandlerGlobal);
00777 CpvDeclare(int, CmiHandlerMax);
00778
00779 static void CmiExtendHandlerTable(int atLeastLen) {
00780 int max = CpvAccess(CmiHandlerMax);
00781 int newmax = (atLeastLen+(atLeastLen>>2)+32);
00782 int bytes = max*sizeof(CmiHandlerInfo);
00783 int newbytes = newmax*sizeof(CmiHandlerInfo);
00784 CmiHandlerInfo *nu = (CmiHandlerInfo*)malloc(newbytes);
00785 CmiHandlerInfo *tab = CpvAccess(CmiHandlerTable);
00786 _MEMCHECK(nu);
00787 if (tab) {
00788 memcpy(nu, tab, bytes);
00789 }
00790 memset(((char *)nu)+bytes, 0, (newbytes-bytes));
00791 free(tab); tab=nu;
00792 CpvAccess(CmiHandlerTable) = tab;
00793 CpvAccess(CmiHandlerMax) = newmax;
00794 }
00795
00796 void CmiAssignOnce(int* variable, int value) {
00797 if (CmiMyRank() == 0) { *variable = value; }
00798 CmiNodeAllBarrier();
00799 }
00800
00801 void CmiNumberHandler(int n, CmiHandler h)
00802 {
00803 CmiHandlerInfo *tab;
00804 if (n >= CpvAccess(CmiHandlerMax)) CmiExtendHandlerTable(n);
00805 tab = CpvAccess(CmiHandlerTable);
00806 tab[n].hdlr = (CmiHandlerEx)h;
00807 tab[n].userPtr = 0;
00808 }
00809 void CmiNumberHandlerEx(int n, CmiHandlerEx h,void *userPtr) {
00810 CmiHandlerInfo *tab;
00811 if (n >= CpvAccess(CmiHandlerMax)) CmiExtendHandlerTable(n);
00812 tab = CpvAccess(CmiHandlerTable);
00813 tab[n].hdlr = h;
00814 tab[n].userPtr=userPtr;
00815 }
00816
00817 #if CMI_LOCAL_GLOBAL_AVAILABLE
00818 # define DIST_BETWEEN_HANDLERS 3
00819 #else
00820 # define DIST_BETWEEN_HANDLERS 1
00821 #endif
00822
00823 int CmiRegisterHandler(CmiHandler h)
00824 {
00825 int Count = CpvAccess(CmiHandlerCount);
00826 CmiNumberHandler(Count, h);
00827 CpvAccess(CmiHandlerCount) = Count+DIST_BETWEEN_HANDLERS;
00828 return Count;
00829 }
00830
00831 void CmiRegisterHandlerAssignOnce(CmiHandler h, int *index)
00832 {
00833 if (CmiMyRank() == 0) { *index = CmiRegisterHandler(h); }
00834 else { CmiRegisterHandler(h); }
00835 CmiBarrier();
00836 }
00837
00838 int CmiRegisterHandlerEx(CmiHandlerEx h,void *userPtr)
00839 {
00840 int Count = CpvAccess(CmiHandlerCount);
00841 CmiNumberHandlerEx(Count, h, userPtr);
00842 CpvAccess(CmiHandlerCount) = Count+DIST_BETWEEN_HANDLERS;
00843 return Count;
00844 }
00845
00846 void CmiRegisterHandlerExAssignOnce(CmiHandlerEx h, void *userPtr, int *index)
00847 {
00848 if (CmiMyRank() == 0) { *index = CmiRegisterHandlerEx(h, userPtr); }
00849 else { CmiRegisterHandlerEx(h, userPtr); }
00850 CmiBarrier();
00851 }
00852
00853 #if CMI_LOCAL_GLOBAL_AVAILABLE
00854 int CmiRegisterHandlerLocal(CmiHandler h)
00855 {
00856 int Local = CpvAccess(CmiHandlerLocal);
00857 CmiNumberHandler(Local, h);
00858 CpvAccess(CmiHandlerLocal) = Local+3;
00859 return Local;
00860 }
00861
00862 int CmiRegisterHandlerGlobal(CmiHandler h)
00863 {
00864 int Global = CpvAccess(CmiHandlerGlobal);
00865 if (CmiMyPe()!=0)
00866 CmiError("CmiRegisterHandlerGlobal must only be called on PE 0.\n");
00867 CmiNumberHandler(Global, h);
00868 CpvAccess(CmiHandlerGlobal) = Global+3;
00869 return Global;
00870 }
00871 #endif
00872
00873 static void _cmiZeroHandler(void *msg) {
00874 CmiAbort("Converse zero handler executed-- was a message corrupted?\n");
00875 }
00876
00877 static void CmiHandlerInit(void)
00878 {
00879 CpvInitialize(CmiHandlerInfo *, CmiHandlerTable);
00880 CpvInitialize(int , CmiHandlerCount);
00881 CpvInitialize(int , CmiHandlerLocal);
00882 CpvInitialize(int , CmiHandlerGlobal);
00883 CpvInitialize(int , CmiHandlerMax);
00884 CpvAccess(CmiHandlerCount) = 0;
00885 CpvAccess(CmiHandlerLocal) = 1;
00886 CpvAccess(CmiHandlerGlobal) = 2;
00887 CpvAccess(CmiHandlerMax) = 0;
00888 CpvAccess(CmiHandlerTable) = NULL;
00889 CmiRegisterHandler((CmiHandler)_cmiZeroHandler);
00890 }
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902 #if CMK_HAS_ASCTIME
00903
00904 char *CmiPrintDate(void)
00905 {
00906 struct tm *local;
00907 time_t t;
00908
00909 t = time(NULL);
00910 local = localtime(&t);
00911 return asctime(local);
00912 }
00913
00914 #else
00915
00916 char *CmiPrintDate(void)
00917 {
00918 return "N/A";
00919 }
00920
00921 #endif
00922
00923 static int _absoluteTime = 0;
00924
00925 #if CMK_TIMER_USE_TIMES
00926
00927 CpvStaticDeclare(double, clocktick);
00928 CpvStaticDeclare(int,inittime_wallclock);
00929 CpvStaticDeclare(int,inittime_virtual);
00930
00931 int CmiTimerIsSynchronized(void)
00932 {
00933 return 0;
00934 }
00935
00936 int CmiTimerAbsolute(void)
00937 {
00938 return 0;
00939 }
00940
00941 double CmiStartTimer(void)
00942 {
00943 return 0.0;
00944 }
00945
00946 double CmiInitTime(void)
00947 {
00948 return CpvAccess(inittime_wallclock);
00949 }
00950
00951 void CmiTimerInit(char **argv)
00952 {
00953 struct tms temp;
00954 CpvInitialize(double, clocktick);
00955 CpvInitialize(int, inittime_wallclock);
00956 CpvInitialize(int, inittime_virtual);
00957 CpvAccess(inittime_wallclock) = times(&temp);
00958 CpvAccess(inittime_virtual) = temp.tms_utime + temp.tms_stime;
00959 CpvAccess(clocktick) = 1.0 / (sysconf(_SC_CLK_TCK));
00960 }
00961
00962 double CmiWallTimer(void)
00963 {
00964 struct tms temp;
00965 double currenttime;
00966 int now;
00967
00968 now = times(&temp);
00969 currenttime = (now - CpvAccess(inittime_wallclock)) * CpvAccess(clocktick);
00970 return (currenttime);
00971 }
00972
00973 double CmiCpuTimer(void)
00974 {
00975 struct tms temp;
00976 double currenttime;
00977 int now;
00978
00979 times(&temp);
00980 now = temp.tms_stime + temp.tms_utime;
00981 currenttime = (now - CpvAccess(inittime_virtual)) * CpvAccess(clocktick);
00982 return (currenttime);
00983 }
00984
00985 double CmiTimer(void)
00986 {
00987 return CmiCpuTimer();
00988 }
00989
00990 #endif
00991
00992 #if CMK_TIMER_USE_GETRUSAGE
00993
00994 #if CMK_SMP
00995 # if CMK_HAS_RUSAGE_THREAD
00996 #define RUSAGE_WHO 1
00997 #else
00998 #undef RUSAGE_WHO
00999 #endif
01000 #else
01001 #define RUSAGE_WHO 0
01002 #endif
01003
01004 static double inittime_wallclock;
01005 CpvStaticDeclare(double, inittime_virtual);
01006
01007 int CmiTimerIsSynchronized(void)
01008 {
01009 return 0;
01010 }
01011
01012 int CmiTimerAbsolute(void)
01013 {
01014 return _absoluteTime;
01015 }
01016
01017 double CmiStartTimer(void)
01018 {
01019 return 0.0;
01020 }
01021
01022 double CmiInitTime(void)
01023 {
01024 return inittime_wallclock;
01025 }
01026
01027 void CmiTimerInit(char **argv)
01028 {
01029 struct rusage ru;
01030 CpvInitialize(double, inittime_virtual);
01031
01032 int tmptime = CmiGetArgFlagDesc(argv,"+useAbsoluteTime", "Use system's absolute time as wallclock time.");
01033 if(CmiMyRank() == 0) _absoluteTime = tmptime;
01034 #if !(__FAULT__)
01035
01036 CmiBarrier();
01037 CmiBarrier();
01038 CmiBarrier();
01039 #endif
01040 if(CmiMyRank() == 0)
01041 {
01042 inittime_wallclock = inithrc();
01043 #ifndef RUSAGE_WHO
01044 CpvAccess(inittime_virtual) = inittime_wallclock;
01045 #else
01046 getrusage(RUSAGE_WHO, &ru);
01047 CpvAccess(inittime_virtual) =
01048 (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
01049 (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
01050 #endif
01051 }
01052
01053 #if !(__FAULT__)
01054 CmiBarrier();
01055
01056 #endif
01057 }
01058
01059 double CmiCpuTimer(void)
01060 {
01061 #ifndef RUSAGE_WHO
01062 return CmiWallTimer();
01063 #else
01064 struct rusage ru;
01065 double currenttime;
01066
01067 getrusage(RUSAGE_WHO, &ru);
01068 currenttime =
01069 (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
01070 (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
01071
01072 return currenttime - CpvAccess(inittime_virtual);
01073 #endif
01074 }
01075
01076 static double lastT = -1.0;
01077
01078 double CmiWallTimer(void)
01079 {
01080 double currenttime;
01081 currenttime = gethrctime();
01082 return _absoluteTime?currenttime+inittime_wallclock:currenttime;
01083 }
01084
01085 double CmiTimer(void)
01086 {
01087 return CmiCpuTimer();
01088 }
01089
01090 #endif
01091
01092 #if CMK_TIMER_USE_RDTSC
01093
01094 static double readMHz(void)
01095 {
01096 double x;
01097 char str[1000];
01098 char buf[100];
01099 FILE *fp;
01100 CmiLock(_smp_mutex);
01101 fp = fopen("/proc/cpuinfo", "r");
01102 if (fp != NULL)
01103 while(fgets(str, 1000, fp)!=0) {
01104 if(sscanf(str, "cpu MHz%[^:]",buf)==1)
01105 {
01106 char *s = strchr(str, ':'); s=s+1;
01107 sscanf(s, "%lf", &x);
01108 fclose(fp);
01109 CmiUnlock(_smp_mutex);
01110 return x;
01111 }
01112 }
01113 CmiUnlock(_smp_mutex);
01114 CmiAbort("Cannot read CPU MHz from /proc/cpuinfo file.");
01115 return 0.0;
01116 }
01117
01118 double _cpu_speed_factor;
01119 CpvStaticDeclare(double, inittime_virtual);
01120 CpvStaticDeclare(double, inittime_walltime);
01121
01122 double CmiStartTimer(void)
01123 {
01124 return CpvAccess(inittime_walltime);
01125 }
01126
01127 double CmiInitTime(void)
01128 {
01129 return CpvAccess(inittime_walltime);
01130 }
01131
01132 void CmiTimerInit(char **argv)
01133 {
01134 struct rusage ru;
01135
01136 CmiBarrier();
01137 CmiBarrier();
01138
01139 _cpu_speed_factor = 1.0/(readMHz()*1.0e6);
01140 rdtsc(); rdtsc(); rdtsc(); rdtsc(); rdtsc();
01141 CpvInitialize(double, inittime_walltime);
01142 CpvAccess(inittime_walltime) = CmiWallTimer();
01143 CpvInitialize(double, inittime_virtual);
01144 getrusage(0, &ru);
01145 CpvAccess(inittime_virtual) =
01146 (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
01147 (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
01148
01149 CmiBarrierZero();
01150 }
01151
01152 double CmiCpuTimer(void)
01153 {
01154 struct rusage ru;
01155 double currenttime;
01156
01157 getrusage(0, &ru);
01158 currenttime =
01159 (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
01160 (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
01161 return currenttime - CpvAccess(inittime_virtual);
01162 }
01163
01164 #endif
01165
01166 #if CMK_TIMER_USE_BLUEGENEQ
01167
01168 CpvStaticDeclare(unsigned long, inittime);
01169 CpvStaticDeclare(double, clocktick);
01170
01171 int CmiTimerIsSynchronized(void)
01172 {
01173 return 1;
01174 }
01175
01176 int CmiTimerAbsolute(void)
01177 {
01178 return 0;
01179 }
01180
01181 #include "hwi/include/bqc/A2_inlines.h"
01182 #include "spi/include/kernel/process.h"
01183
01184 double CmiStartTimer(void)
01185 {
01186 return 0.0;
01187 }
01188
01189 double CmiInitTime(void)
01190 {
01191 return CpvAccess(inittime);
01192 }
01193
01194 void CmiTimerInit(char **argv)
01195 {
01196 CpvInitialize(double, clocktick);
01197 CpvInitialize(unsigned long, inittime);
01198
01199 Personality_t pers;
01200 Kernel_GetPersonality(&pers, sizeof(pers));
01201 uint32_t clockMhz = pers.Kernel_Config.FreqMHz;
01202 CpvAccess(clocktick) = 1.0 / (clockMhz * 1e6);
01203
01204
01205
01206
01207 #if !(__FAULT__)
01208 CmiBarrier();
01209 CmiBarrier();
01210 CmiBarrier();
01211 #endif
01212 CpvAccess(inittime) = GetTimeBase ();
01213 }
01214
01215 double CmiWallTimer(void)
01216 {
01217 unsigned long long currenttime;
01218 currenttime = GetTimeBase();
01219 return CpvAccess(clocktick)*(currenttime-CpvAccess(inittime));
01220 }
01221
01222 double CmiCpuTimer(void)
01223 {
01224 return CmiWallTimer();
01225 }
01226
01227 double CmiTimer(void)
01228 {
01229 return CmiWallTimer();
01230 }
01231
01232 #endif
01233
01234
01235 #if CMK_TIMER_USE_PPC64
01236
01237 #include <sys/time.h>
01238 #include <sys/platform/ppc.h>
01239
01240 CpvStaticDeclare(uint64_t, inittime);
01241 CpvStaticDeclare(double, clocktick);
01242
01243 int CmiTimerIsSynchronized(void)
01244 {
01245 return 1;
01246 }
01247
01248 int CmiTimerAbsolute(void)
01249 {
01250 return 0;
01251 }
01252
01253 double CmiStartTimer(void)
01254 {
01255 return 0.0;
01256 }
01257
01258 double CmiInitTime(void)
01259 {
01260 return CpvAccess(inittime);
01261 }
01262
01263 static inline uint64_t PPC64_TimeBase(void)
01264 {
01265 register volatile uint64_t result;
01266
01267
01268 asm volatile (
01269 " isync \n\t"
01270 " mftb %0 \n\t"
01271 " isync \n\t"
01272 : "=r"(result));
01273
01274 return result;
01275 }
01276
01277 void CmiTimerInit(char **argv)
01278 {
01279 CpvInitialize(double, clocktick);
01280 CpvInitialize(unsigned long, inittime);
01281 CpvAccess(clocktick) = 1.0 / ((double) __ppc_get_timebase_freq());
01282
01283
01284 #if !(__FAULT__)
01285 CmiBarrier();
01286 CmiBarrier();
01287 CmiBarrier();
01288 #endif
01289 CpvAccess(inittime) = PPC64_TimeBase ();
01290 }
01291
01292 double CmiWallTimer(void)
01293 {
01294 uint64_t currenttime;
01295 currenttime = PPC64_TimeBase();
01296 return CpvAccess(clocktick)*(currenttime-CpvAccess(inittime));
01297 }
01298
01299 double CmiCpuTimer(void)
01300 {
01301 return CmiWallTimer();
01302 }
01303
01304 double CmiTimer(void)
01305 {
01306 return CmiWallTimer();
01307 }
01308
01309 #endif
01310
01311
01312 #if CMK_TIMER_USE_WIN32API
01313
01314 CpvStaticDeclare(double, inittime_wallclock);
01315 CpvStaticDeclare(double, inittime_virtual);
01316
01317 double CmiStartTimer(void)
01318 {
01319 return 0.0;
01320 }
01321
01322 int CmiTimerAbsolute(void)
01323 {
01324 return 0;
01325 }
01326
01327 double CmiInitTime(void)
01328 {
01329 return CpvAccess(inittime_wallclock);
01330 }
01331
01332 void CmiTimerInit(char **argv)
01333 {
01334 struct timeb tv;
01335 clock_t ru;
01336
01337 CpvInitialize(double, inittime_wallclock);
01338 CpvInitialize(double, inittime_virtual);
01339 ftime(&tv);
01340 CpvAccess(inittime_wallclock) = tv.time*1.0 + tv.millitm*0.001;
01341 ru = clock();
01342 CpvAccess(inittime_virtual) = ((double) ru)/CLOCKS_PER_SEC;
01343 }
01344
01345 double CmiCpuTimer(void)
01346 {
01347 clock_t ru;
01348 double currenttime;
01349
01350 ru = clock();
01351 currenttime = (double) ru/CLOCKS_PER_SEC;
01352
01353 return currenttime - CpvAccess(inittime_virtual);
01354 }
01355
01356 double CmiWallTimer(void)
01357 {
01358 struct timeb tv;
01359 double currenttime;
01360
01361 ftime(&tv);
01362 currenttime = tv.time*1.0 + tv.millitm*0.001;
01363
01364 return currenttime - CpvAccess(inittime_wallclock);
01365 }
01366
01367
01368 double CmiTimer(void)
01369 {
01370 return CmiCpuTimer();
01371 }
01372
01373 #endif
01374
01375 #if CMK_TIMER_USE_RTC
01376
01377 static double clocktick;
01378 CpvStaticDeclare(long long, inittime_wallclock);
01379
01380 double CmiStartTimer(void)
01381 {
01382 return 0.0;
01383 }
01384
01385 double CmiInitTime(void)
01386 {
01387 return CpvAccess(inittime_wallclock);
01388 }
01389
01390 void CmiTimerInit(char **argv)
01391 {
01392 CpvInitialize(long long, inittime_wallclock);
01393 CpvAccess(inittime_wallclock) = _rtc();
01394 clocktick = 1.0 / (double)(sysconf(_SC_SV2_USER_TIME_RATE));
01395 }
01396
01397 int CmiTimerAbsolute(void)
01398 {
01399 return 0;
01400 }
01401
01402 double CmiWallTimer(void)
01403 {
01404 long long now;
01405
01406 now = _rtc();
01407 return (clocktick * (now - CpvAccess(inittime_wallclock)));
01408 }
01409
01410 double CmiCpuTimer(void)
01411 {
01412 return CmiWallTimer();
01413 }
01414
01415 double CmiTimer(void)
01416 {
01417 return CmiCpuTimer();
01418 }
01419
01420 #endif
01421
01422 #if CMK_TIMER_USE_AIX_READ_TIME
01423
01424 #include <sys/time.h>
01425
01426 static timebasestruct_t inittime_wallclock;
01427 static double clocktick;
01428 CpvStaticDeclare(double, inittime_virtual);
01429
01430 double CmiStartTimer(void)
01431 {
01432 return 0.0;
01433 }
01434
01435 double CmiInitTime(void)
01436 {
01437 return inittime_wallclock;
01438 }
01439
01440 void CmiTimerInit(char **argv)
01441 {
01442 struct rusage ru;
01443
01444 if (CmiMyRank() == 0) {
01445 read_wall_time(&inittime_wallclock, TIMEBASE_SZ);
01446 time_base_to_time(&inittime_wallclock, TIMEBASE_SZ);
01447 }
01448
01449 CpvInitialize(double, inittime_virtual);
01450 getrusage(0, &ru);
01451 CpvAccess(inittime_virtual) =
01452 (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
01453 (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
01454 }
01455
01456 int CmiTimerAbsolute(void)
01457 {
01458 return 0;
01459 }
01460
01461 double CmiWallTimer(void)
01462 {
01463 int secs, n_secs;
01464 double curt;
01465 timebasestruct_t now;
01466 read_wall_time(&now, TIMEBASE_SZ);
01467 time_base_to_time(&now, TIMEBASE_SZ);
01468
01469 secs = now.tb_high - inittime_wallclock.tb_high;
01470 n_secs = now.tb_low - inittime_wallclock.tb_low;
01471 if (n_secs < 0) {
01472 secs--;
01473 n_secs += 1000000000;
01474 }
01475 curt = secs*1.0 + n_secs*1e-9;
01476 return curt;
01477 }
01478
01479 double CmiCpuTimer(void)
01480 {
01481 struct rusage ru;
01482 double currenttime;
01483
01484 getrusage(0, &ru);
01485 currenttime =
01486 (ru.ru_utime.tv_sec * 1.0)+(ru.ru_utime.tv_usec * 0.000001) +
01487 (ru.ru_stime.tv_sec * 1.0)+(ru.ru_stime.tv_usec * 0.000001);
01488 return currenttime - CpvAccess(inittime_virtual);
01489 }
01490
01491 double CmiTimer(void)
01492 {
01493 return CmiWallTimer();
01494 }
01495
01496 #endif
01497
01498 #ifndef CMK_USE_SPECIAL_MESSAGE_QUEUE_CHECK
01499
01501 int CmiLongSendQueue(int forNode,int longerThanBytes) {
01502 return 0;
01503 }
01504 #endif
01505
01506 #if CMK_SIGNAL_USE_SIGACTION
01507 #include <signal.h>
01508 void CmiSignal(int sig1, int sig2, int sig3, void (*handler)(int))
01509 {
01510 struct sigaction in, out ;
01511 in.sa_handler = handler;
01512 sigemptyset(&in.sa_mask);
01513 if (sig1) sigaddset(&in.sa_mask, sig1);
01514 if (sig2) sigaddset(&in.sa_mask, sig2);
01515 if (sig3) sigaddset(&in.sa_mask, sig3);
01516 in.sa_flags = 0;
01517 if (sig1) if (sigaction(sig1, &in, &out)<0) exit(1);
01518 if (sig2) if (sigaction(sig2, &in, &out)<0) exit(1);
01519 if (sig3) if (sigaction(sig3, &in, &out)<0) exit(1);
01520 }
01521 #endif
01522
01523 #if CMK_SIGNAL_USE_SIGACTION_WITH_RESTART
01524 #include <signal.h>
01525 void CmiSignal(int sig1, int sig2, int sig3, void (*handler)(int))
01526 {
01527 struct sigaction in, out ;
01528 in.sa_handler = handler;
01529 sigemptyset(&in.sa_mask);
01530 if (sig1) sigaddset(&in.sa_mask, sig1);
01531 if (sig2) sigaddset(&in.sa_mask, sig2);
01532 if (sig3) sigaddset(&in.sa_mask, sig3);
01533 in.sa_flags = SA_RESTART;
01534 if (sig1) if (sigaction(sig1, &in, &out)<0) exit(1);
01535 if (sig2) if (sigaction(sig2, &in, &out)<0) exit(1);
01536 if (sig3) if (sigaction(sig3, &in, &out)<0) exit(1);
01537 }
01538 #endif
01539
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584 void CsdBeginIdle(void)
01585 {
01586 CcdCallBacks();
01587 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
01588 _LOG_E_PROC_IDLE();
01589 #endif
01590 #if CMK_SMP && CMK_TASKQUEUE
01591 if (CpvAccess(cmiMyPeIdle) !=1) {
01592 CpvAccess(cmiMyPeIdle) = 1;
01593 CmiMemoryAtomicIncrement(CsvAccess(idleThreadsCnt), memory_order_relaxed);
01594 }
01595 #else
01596 CpvAccess(cmiMyPeIdle) = 1;
01597 #endif // CMK_SMP
01598 CcdRaiseCondition(CcdPROCESSOR_BEGIN_IDLE) ;
01599 }
01600
01601 void CsdStillIdle(void)
01602 {
01603 CcdRaiseCondition(CcdPROCESSOR_STILL_IDLE);
01604 }
01605
01606 void CsdEndIdle(void)
01607 {
01608 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
01609 _LOG_E_PROC_BUSY();
01610 #endif
01611 #if CMK_SMP && CMK_TASKQUEUE
01612 if (CpvAccess(cmiMyPeIdle) != 0){
01613 CpvAccess(cmiMyPeIdle) = 0;
01614 CmiMemoryAtomicDecrement(CsvAccess(idleThreadsCnt), memory_order_relaxed);
01615 }
01616 #else
01617 CpvAccess(cmiMyPeIdle) = 0;
01618 #endif // CMK_SMP
01619 CcdRaiseCondition(CcdPROCESSOR_BEGIN_BUSY) ;
01620 }
01621
01622 extern int _exitHandlerIdx;
01623
01625 void CmiHandleMessage(void *msg)
01626 {
01627
01628
01629
01630 CmiHandlerInfo *h;
01631 CmiUInt2 handlerIdx=CmiGetHandler(msg);
01632 #if CMK_TRACE_ENABLED && CMK_PROJECTOR
01633 _LOG_E_HANDLER_BEGIN(handlerIdx);
01634
01635 #endif
01636
01637
01638
01639
01640
01641
01642
01643
01644 MESSAGE_PHASE_CHECK(msg)
01645 #if CMK_ERROR_CHECKING
01646 if (handlerIdx >= CpvAccess(CmiHandlerCount)) {
01647 CmiAbort("Msg handler does not exist, possible race condition during init\n");
01648 }
01649 #endif
01650 h=&CmiHandlerToInfo(handlerIdx);
01651 #if CMK_ERROR_CHECKING
01652 if (h->hdlr == NULL) {
01653 CmiAbort("Msg handler does not exist, possible race condition during init\n");
01654 }
01655 #endif
01656 (h->hdlr)(msg,h->userPtr);
01657 #if CMK_TRACE_ENABLED
01658
01659
01660 #endif
01661 }
01662
01663 #if CMK_CMIDELIVERS_USE_COMMON_CODE
01664
01665 void CmiDeliversInit(void)
01666 {
01667 }
01668
01669 int CmiDeliverMsgs(int maxmsgs)
01670 {
01671 return CsdScheduler(maxmsgs);
01672 }
01673
01674 #if CMK_OBJECT_QUEUE_AVAILABLE
01675 CpvDeclare(void *, CsdObjQueue);
01676 #endif
01677
01678 void CsdSchedulerState_new(CsdSchedulerState_t *s)
01679 {
01680 #if CMK_OBJECT_QUEUE_AVAILABLE
01681 s->objQ=CpvAccess(CsdObjQueue);
01682 #endif
01683 s->localQ=CpvAccess(CmiLocalQueue);
01684 s->schedQ=CpvAccess(CsdSchedQueue);
01685 s->localCounter=&(CpvAccess(CsdLocalCounter));
01686 #if CMK_NODE_QUEUE_AVAILABLE
01687 s->nodeQ=CsvAccess(CsdNodeQueue);
01688 s->nodeLock=CsvAccess(CsdNodeQueueLock);
01689 #endif
01690 #if CMK_GRID_QUEUE_AVAILABLE
01691 s->gridQ=CpvAccess(CsdGridQueue);
01692 #endif
01693 #if CMK_SMP && CMK_TASKQUEUE
01694 s->taskQ = CpvAccess(CsdTaskQueue);
01695 s->suspendedTaskQ = CpvAccess(CmiSuspendedTaskQueue);
01696 #endif
01697 }
01698
01699
01750 void *CsdNextMessage(CsdSchedulerState_t *s) {
01751 void *msg;
01752 if((*(s->localCounter))-- >0)
01753 {
01754
01755 msg=CdsFifo_Dequeue(s->localQ);
01756 if (msg!=NULL)
01757 {
01758 #if CMI_QD
01759 CpvAccess(cQdState)->mProcessed++;
01760 #endif
01761 return msg;
01762 }
01763 CqsDequeue(s->schedQ,(void **)&msg);
01764 if (msg!=NULL) return msg;
01765 }
01766
01767 *(s->localCounter)=CsdLocalMax;
01768 if ( NULL!=(msg=CmiGetNonLocal()) ||
01769 NULL!=(msg=CdsFifo_Dequeue(s->localQ)) ) {
01770 #if CMI_QD
01771 CpvAccess(cQdState)->mProcessed++;
01772 #endif
01773 return msg;
01774 }
01775 #if CMK_GRID_QUEUE_AVAILABLE
01776
01777 CqsDequeue (s->gridQ, (void **) &msg);
01778 if (msg != NULL) {
01779 return (msg);
01780 }
01781 #endif
01782 #if CMK_SMP && CMK_TASKQUEUE
01783 #if CMK_OMP
01784 msg = CmiSuspendedTaskPop();
01785 if (msg != NULL) {
01786 return (msg);
01787 }
01788 #endif
01789 msg = TaskQueuePop((TaskQueue)s->taskQ);
01790 if (msg != NULL) {
01791 return (msg);
01792 }
01793 #endif
01794 #if CMK_NODE_QUEUE_AVAILABLE
01795
01796 if (NULL!=(msg=CmiGetNonLocalNodeQ())) return msg;
01797 #if !CMK_NO_MSG_PRIOS
01798 if (!CqsEmpty(s->nodeQ)
01799 && CqsPrioGT(CqsGetPriority(s->schedQ),
01800 CqsGetPriority(s->nodeQ))) {
01801 if(CmiTryLock(s->nodeLock) == 0) {
01802 CqsDequeue(s->nodeQ,(void **)&msg);
01803 CmiUnlock(s->nodeLock);
01804 if (msg!=NULL) return msg;
01805 }
01806 }
01807 #endif
01808 #endif
01809 #if CMK_OBJECT_QUEUE_AVAILABLE
01810
01811 if (NULL!=(msg=CdsFifo_Dequeue(s->objQ))) {
01812 return msg;
01813 }
01814 #endif
01815 if(!CsdLocalMax) {
01816 CqsDequeue(s->schedQ,(void **)&msg);
01817 if (msg!=NULL) return msg;
01818 }
01819 return NULL;
01820 }
01821
01822
01823 void *CsdNextLocalNodeMessage(CsdSchedulerState_t *s) {
01824 void *msg;
01825 #if CMK_NODE_QUEUE_AVAILABLE
01826
01827
01828 if (!CqsEmpty(s->nodeQ))
01829 {
01830 CmiLock(s->nodeLock);
01831 CqsDequeue(s->nodeQ,(void **)&msg);
01832 CmiUnlock(s->nodeLock);
01833 if (msg!=NULL) return msg;
01834 }
01835 #endif
01836 return NULL;
01837
01838 }
01839
01840 int CsdScheduler(int maxmsgs)
01841 {
01842 if (maxmsgs<0) CsdScheduleForever();
01843 else if (maxmsgs==0)
01844 CsdSchedulePoll();
01845 else
01846 return CsdScheduleCount(maxmsgs);
01847 return 0;
01848 }
01849
01850
01851 #define SCHEDULE_TOP \
01852 void *msg;\
01853 int *CsdStopFlag_ptr = &CpvAccess(CsdStopFlag); \
01854 int cycle = CpvAccess(CsdStopFlag); \
01855 CsdSchedulerState_t state;\
01856 CsdSchedulerState_new(&state);
01857
01858
01859 #define SCHEDULE_MESSAGE \
01860 CmiHandleMessage(msg);\
01861 if (*CsdStopFlag_ptr != cycle) break;
01862
01863
01864 #if CSD_NO_IDLE_TRACING
01865 #define SCHEDULE_IDLE
01866 #else
01867 #define SCHEDULE_IDLE \
01868 if (!isIdle) {isIdle=1;CsdBeginIdle();}\
01869 else CsdStillIdle();\
01870 if (*CsdStopFlag_ptr != cycle) {\
01871 CsdEndIdle();\
01872 break;\
01873 }
01874 #endif
01875
01876
01877
01878
01879
01880
01881 extern void machine_OffloadAPIProgress(void);
01882
01884 void CsdScheduleForever(void)
01885 {
01886 #if CMK_CELL
01887 #define CMK_CELL_PROGRESS_FREQ 96
01888 int progressCount = CMK_CELL_PROGRESS_FREQ;
01889 #endif
01890
01891 int isIdle=0;
01892 SCHEDULE_TOP
01893 while (1) {
01894 #if !CMK_NO_INTEROP
01895
01896 if(CharmLibInterOperate) {
01897 if(CpvAccess(interopExitFlag)) {
01898 CpvAccess(interopExitFlag) = 0;
01899 break;
01900 }
01901 }
01902 #endif
01903 #if CMK_CUDA
01904
01905 if (CpvAccess(n_hapi_events) > 0) {
01906 hapiPollEvents();
01907 }
01908 #endif
01909 msg = CsdNextMessage(&state);
01910 if (msg!=NULL) {
01911 #if !CSD_NO_IDLE_TRACING
01912 if (isIdle) {isIdle=0;CsdEndIdle();}
01913 #endif
01914 SCHEDULE_MESSAGE
01915
01916 #if CMK_CELL
01917 if (progressCount <= 0) {
01918
01919 machine_OffloadAPIProgress();
01920 progressCount = CMK_CELL_PROGRESS_FREQ;
01921 }
01922 progressCount--;
01923 #endif
01924 } else {
01925 SCHEDULE_IDLE
01926
01927 #if CMK_CELL
01928
01929 machine_OffloadAPIProgress();
01930 progressCount = CMK_CELL_PROGRESS_FREQ;
01931 #endif
01932 }
01933 #if !CSD_NO_PERIODIC
01934 CsdPeriodic();
01935 #endif
01936 }
01937 }
01938 int CsdScheduleCount(int maxmsgs)
01939 {
01940 int isIdle=0;
01941 SCHEDULE_TOP
01942 while (1) {
01943 msg = CsdNextMessage(&state);
01944 if (msg!=NULL) {
01945 #if !CSD_NO_IDLE_TRACING
01946 if (isIdle) {isIdle=0;CsdEndIdle();}
01947 #endif
01948 maxmsgs--;
01949 SCHEDULE_MESSAGE
01950 if (maxmsgs==0) break;
01951 } else {
01952 SCHEDULE_IDLE
01953 }
01954 #if !CSD_NO_PERIODIC
01955 CsdPeriodic();
01956 #endif
01957 }
01958 return maxmsgs;
01959 }
01960
01961 void CsdSchedulePoll(void)
01962 {
01963 SCHEDULE_TOP
01964 while (1)
01965 {
01966 #if !CSD_NO_PERIODIC
01967 CsdPeriodic();
01968 #endif
01969
01970 if (NULL!=(msg = CsdNextMessage(&state)))
01971 {
01972 SCHEDULE_MESSAGE
01973 }
01974 else break;
01975 }
01976 }
01977
01978 void CsdScheduleNodePoll(void)
01979 {
01980 SCHEDULE_TOP
01981 while (1)
01982 {
01983
01984
01985 if (NULL!=(msg = CsdNextLocalNodeMessage(&state)))
01986 {
01987 SCHEDULE_MESSAGE
01988 }
01989 else break;
01990 }
01991 }
01992
01993 void CmiDeliverSpecificMsg(int handler)
01994 {
01995 int *msg; int side;
01996 void *localqueue = CpvAccess(CmiLocalQueue);
01997
01998 side = 0;
01999 while (1) {
02000 #if !CSD_NO_PERIODIC
02001 CsdPeriodic();
02002 #endif
02003 side ^= 1;
02004 if (side) msg = (int *)CmiGetNonLocal();
02005 else msg = (int *)CdsFifo_Dequeue(localqueue);
02006 if (msg) {
02007 if (CmiGetHandler(msg)==handler) {
02008 #if CMI_QD
02009 CpvAccess(cQdState)->mProcessed++;
02010 #endif
02011 CmiHandleMessage(msg);
02012 return;
02013 } else {
02014 CdsFifo_Enqueue(localqueue, msg);
02015 }
02016 }
02017 }
02018 }
02019
02020 #endif
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045 CpvStaticDeclare(CthThread, CthMainThread);
02046 CpvStaticDeclare(CthThread, CthSchedulingThread);
02047 CpvStaticDeclare(CthThread, CthSleepingStandins);
02048 CpvDeclare(int , CthResumeNormalThreadIdx);
02049 CpvStaticDeclare(int , CthResumeSchedulingThreadIdx);
02050
02051 #if CMK_OMP
02052 CpvDeclare (int, CthResumeStealableThreadIdx);
02053 CpvDeclare (int, CthResumeSuspendedStealableThreadIdx);
02054 #endif
02055
02056 void CthStandinCode(void *arg)
02057 {
02058 CsdScheduler(-1);
02059 }
02060
02061
02062 static CthThread CthSuspendNormalThread(void)
02063 {
02064 return CpvAccess(CthSchedulingThread);
02065 }
02066
02067 void CthEnqueueSchedulingThread(CthThreadToken *token, int, int, unsigned int*);
02068 CthThread CthSuspendSchedulingThread(void);
02069
02070 CthThread CthSuspendSchedulingThread(void)
02071 {
02072 CthThread succ = CpvAccess(CthSleepingStandins);
02073
02074 if (succ) {
02075 CpvAccess(CthSleepingStandins) = CthGetNext(succ);
02076 } else {
02077 succ = CthCreate(CthStandinCode, 0, 256000);
02078 CthSetStrategy(succ,
02079 CthEnqueueSchedulingThread,
02080 CthSuspendSchedulingThread);
02081 }
02082
02083 CpvAccess(CthSchedulingThread) = succ;
02084 return succ;
02085 }
02086
02087
02088 void CthResumeNormalThread(CthThreadToken* token)
02089 {
02090 CthThread t = token->thread;
02091
02092
02093
02094
02095
02096 if(t == NULL){
02097 free(token);
02098 return;
02099 }
02100 #if CMK_TRACE_ENABLED
02101 #if ! CMK_TRACE_IN_CHARM
02102 if(CpvAccess(traceOn))
02103 CthTraceResume(t);
02104
02105
02106 #endif
02107 #endif
02108
02109
02110
02111
02112
02113 #if CMK_OMP
02114 CthSetPrev(t, CthSelf());
02115 #endif
02116 CthResume(t);
02117 #if CMK_OMP
02118 CthScheduledDecrement();
02119 CthSetPrev(CthSelf(), 0);
02120 #endif
02121 }
02122
02123 void CthResumeSchedulingThread(CthThreadToken *token)
02124 {
02125 CthThread t = token->thread;
02126 CthThread me = CthSelf();
02127 if (me == CpvAccess(CthMainThread)) {
02128 CthEnqueueSchedulingThread(CthGetToken(me),CQS_QUEUEING_FIFO, 0, 0);
02129 } else {
02130 CthSetNext(me, CpvAccess(CthSleepingStandins));
02131 CpvAccess(CthSleepingStandins) = me;
02132 }
02133 CpvAccess(CthSchedulingThread) = t;
02134 #if CMK_TRACE_ENABLED
02135 #if ! CMK_TRACE_IN_CHARM
02136 if(CpvAccess(traceOn))
02137 CthTraceResume(t);
02138
02139
02140 #endif
02141 #endif
02142 #if CMK_OMP
02143 CthSetPrev(t, CthSelf());
02144 #endif
02145 CthResume(t);
02146 #if CMK_OMP
02147 CthScheduledDecrement();
02148 CthSetPrev(CthSelf(), 0);
02149 #endif
02150 }
02151
02152 void CthEnqueueNormalThread(CthThreadToken* token, int s,
02153 int pb,unsigned int *prio)
02154 {
02155 CmiSetHandler(token, CpvAccess(CthResumeNormalThreadIdx));
02156 CsdEnqueueGeneral(token, s, pb, prio);
02157 }
02158
02159 void CthEnqueueSchedulingThread(CthThreadToken* token, int s,
02160 int pb,unsigned int *prio)
02161 {
02162 CmiSetHandler(token, CpvAccess(CthResumeSchedulingThreadIdx));
02163 CsdEnqueueGeneral(token, s, pb, prio);
02164 }
02165
02166 void CthSetStrategyDefault(CthThread t)
02167 {
02168 CthSetStrategy(t,
02169 CthEnqueueNormalThread,
02170 CthSuspendNormalThread);
02171 }
02172 #if CMK_OMP
02173
02174
02175
02176 void CthResumeStealableThread(CthThreadToken *token)
02177 {
02178 CthThread t = token->thread;
02179 CthSetNext(t, CthSelf());
02180 #if CMK_TRACE_ENABLED
02181 #if ! CMK_TRACE_IN_CHARM
02182 if(CpvAccess(traceOn))
02183 CthTraceResume(t);
02184 #endif
02185 #endif
02186 CthSetPrev(t, CthSelf());
02187 CthResume(t);
02188 CthScheduledDecrement();
02189 CthSetPrev(CthSelf(), 0);
02190 }
02191
02192 void CthEnqueueStealableThread(CthThreadToken * token, int s, int pb, unsigned int *prio) {
02193 CmiSetHandler(token, CpvAccess(CthResumeStealableThreadIdx));
02194 CsdTaskEnqueue((void*)token);
02195 }
02196
02197
02198 void CthEnqueueSuspendedStealableThread(CthThreadToken * token, int s, int pb, unsigned int *prio)
02199 {
02200 CthThread t = token->thread;
02201 int targetRank = CthGetThreadID(t)->id[2];
02202 CthSetStrategyWorkStealing(t);
02203 if (targetRank == CmiMyRank()) {
02204 CthEnqueueStealableThread(token,s,pb,prio);
02205 }
02206 else {
02207 CmiSetHandler(token, CpvAccess(CthResumeSuspendedStealableThreadIdx));
02208 CmiSuspendedTaskEnqueue(targetRank ,(void*)token);
02209 }
02210 }
02211
02212 void CthResumeSuspendedStealableThread(CthThreadToken *token) {
02213 CthEnqueueStealableThread(token, 0, 0, NULL);
02214 }
02215
02216 CthThread CthSuspendStealableThread()
02217 {
02218 CthThread succ = CthGetNext(CthSelf());
02219 #if CMK_ERROR_CHECKING
02220 if (!succ)
02221 CmiAbort("successor is invalid\n");
02222 #endif
02223 return succ;
02224 }
02225
02226 void CthSetStrategyWorkStealing(CthThread t)
02227 {
02228 CthSetStrategy(t, CthEnqueueStealableThread, CthSuspendStealableThread);
02229 }
02230
02231 void CthSetStrategySuspendedWorkStealing(CthThread t)
02232 {
02233 CthSetStrategy(t, CthEnqueueSuspendedStealableThread, CthSuspendStealableThread);
02234 }
02235
02236 #endif
02237 void CthSchedInit()
02238 {
02239 CpvInitialize(CthThread, CthMainThread);
02240 CpvInitialize(CthThread, CthSchedulingThread);
02241 CpvInitialize(CthThread, CthSleepingStandins);
02242 CpvInitialize(int , CthResumeNormalThreadIdx);
02243 CpvInitialize(int , CthResumeSchedulingThreadIdx);
02244 #if CMK_OMP
02245 CpvInitialize(int , CthResumeStealableThreadIdx);
02246 CpvInitialize(int , CthResumeSuspendedStealableThreadIdx);
02247 #endif
02248 CpvAccess(CthMainThread) = CthSelf();
02249 CpvAccess(CthSchedulingThread) = CthSelf();
02250 CpvAccess(CthSleepingStandins) = 0;
02251 CpvAccess(CthResumeNormalThreadIdx) =
02252 CmiRegisterHandler((CmiHandler)CthResumeNormalThread);
02253 CpvAccess(CthResumeSchedulingThreadIdx) =
02254 CmiRegisterHandler((CmiHandler)CthResumeSchedulingThread);
02255 CthSetStrategy(CthSelf(),
02256 CthEnqueueSchedulingThread,
02257 CthSuspendSchedulingThread);
02258
02259 #if CMK_OMP
02260 CpvAccess(CthResumeStealableThreadIdx) = CmiRegisterHandler((CmiHandler)CthResumeStealableThread);
02261 CpvAccess(CthResumeSuspendedStealableThreadIdx) = CmiRegisterHandler((CmiHandler)CthResumeSuspendedStealableThread);
02262 #endif
02263 }
02264
02265 void CsdInit(char **argv)
02266 {
02267 CpvInitialize(Queue, CsdSchedQueue);
02268 CpvInitialize(int, CsdStopFlag);
02269 CpvInitialize(int, CsdLocalCounter);
02270 int argCsdLocalMax=CSD_LOCAL_MAX_DEFAULT;
02271 int argmaxset = CmiGetArgIntDesc(argv,"+csdLocalMax",&argCsdLocalMax,"Set the max number of local messages to process before forcing a check for remote messages.");
02272 if (CmiMyRank() == 0 ) CsdLocalMax = argCsdLocalMax;
02273 CpvAccess(CsdLocalCounter) = argCsdLocalMax;
02274 CpvAccess(CsdSchedQueue) = CqsCreate();
02275 #if CMK_SMP && CMK_TASKQUEUE
02276 CsvInitialize(unsigned int, idleThreadsCnt);
02277 CsvAccess(idleThreadsCnt) = 0;
02278 #endif
02279 #if CMK_USE_STL_MSGQ
02280 if (CmiMyPe() == 0) CmiPrintf("Charm++> Using STL-based msgQ:\n");
02281 #endif
02282 #if CMK_RANDOMIZED_MSGQ
02283 if (CmiMyPe() == 0) CmiPrintf("Charm++> Using randomized msgQ. Priorities will not be respected!\n");
02284 #elif CMK_NO_MSG_PRIOS
02285 if (CmiMyPe() == 0) CmiPrintf("Charm++> Message priorities have been turned off and will not be respected.\n");
02286 #endif
02287
02288 #if CMK_OBJECT_QUEUE_AVAILABLE
02289 CpvInitialize(Queue, CsdObjQueue);
02290 CpvAccess(CsdObjQueue) = CdsFifo_Create();
02291 #endif
02292
02293 #if CMK_NODE_QUEUE_AVAILABLE
02294 CsvInitialize(CmiLock, CsdNodeQueueLock);
02295 CsvInitialize(Queue, CsdNodeQueue);
02296 if (CmiMyRank() ==0) {
02297 CsvAccess(CsdNodeQueueLock) = CmiCreateLock();
02298 CsvAccess(CsdNodeQueue) = CqsCreate();
02299 }
02300 CmiNodeAllBarrier();
02301 #endif
02302
02303 #if CMK_GRID_QUEUE_AVAILABLE
02304 CsvInitialize(Queue, CsdGridQueue);
02305 CpvAccess(CsdGridQueue) = CqsCreate();
02306 #endif
02307
02308 #if CMK_SMP && CMK_TASKQUEUE
02309 CpvInitialize(Queue, CsdTaskQueue);
02310 CpvInitialize(void *, CmiSuspendedTaskQueue);
02311 CpvAccess(CsdTaskQueue) = (Queue)TaskQueueCreate();
02312 #endif
02313 CpvAccess(CsdStopFlag) = 0;
02314 CpvInitialize(int, isHelperOn);
02315 CpvAccess(isHelperOn) = 1;
02316 CmiMemoryWriteFence();
02317 #if CMK_SMP && CMK_TASKQUEUE
02318 CmiTaskQueueInit();
02319 #endif
02320 }
02321
02322
02323
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342 #if CMK_VECTOR_SEND_USES_COMMON_CODE
02343
02344 void CmiSyncVectorSend(int destPE, int n, int *sizes, char **msgs) {
02345 int total;
02346 char *mesg;
02347 #if CMK_USE_IBVERBS
02348 VECTOR_COMPACT(total, mesg, n, sizes, msgs,sizeof(infiCmiChunkHeader));
02349 #else
02350 VECTOR_COMPACT(total, mesg, n, sizes, msgs,sizeof(CmiChunkHeader));
02351 #endif
02352 CmiSyncSendAndFree(destPE, total, mesg);
02353 }
02354
02355 CmiCommHandle CmiASyncVectorSend(int destPE, int n, int *sizes, char **msgs) {
02356 CmiSyncVectorSend(destPE, n, sizes, msgs);
02357 return NULL;
02358 }
02359
02360 void CmiSyncVectorSendAndFree(int destPE, int n, int *sizes, char **msgs) {
02361 int i;
02362 CmiSyncVectorSend(destPE, n, sizes, msgs);
02363 for(i=0;i<n;i++) CmiFree(msgs[i]);
02364 CmiFree(sizes);
02365 CmiFree(msgs);
02366 }
02367
02368 #endif
02369
02370
02371
02372
02373
02374
02375
02376
02377
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412 CpvStaticDeclare(int, CmiReductionMessageHandler);
02413 CpvStaticDeclare(int, CmiReductionDynamicRequestHandler);
02414
02415 CpvStaticDeclare(CmiReduction**, _reduce_info);
02416 CpvStaticDeclare(int, _reduce_info_size);
02417 CpvStaticDeclare(CmiUInt2, _reduce_seqID_global);
02418 CpvStaticDeclare(CmiUInt2, _reduce_seqID_request);
02419 CpvStaticDeclare(CmiUInt2, _reduce_seqID_dynamic);
02420
02421 enum {
02422 CmiReductionID_globalOffset = 0,
02423 CmiReductionID_requestOffset = 1,
02424 CmiReductionID_dynamicOffset = 2,
02425 CmiReductionID_multiplier = 3
02426 };
02427
02428 CmiReduction* CmiGetReductionCreate(int id, short int numChildren) {
02429 int index = id & ~((~0u)<<CpvAccess(_reduce_info_size));
02430 CmiReduction *red = CpvAccess(_reduce_info)[index];
02431 if (red != NULL && red->seqID != id) {
02432
02433 CmiAbort("Too many simultaneous reductions");
02434 }
02435 if (red == NULL || red->numChildren < numChildren) {
02436 CmiReduction *newred;
02437 CmiAssert(red == NULL || red->localContributed == 0);
02438 if (numChildren == 0) numChildren = 4;
02439 newred = (CmiReduction*)malloc(sizeof(CmiReduction)+numChildren*sizeof(void*));
02440 newred->numRemoteReceived = 0;
02441 newred->localContributed = 0;
02442 newred->seqID = id;
02443 if (red != NULL) {
02444 memcpy(newred, red, sizeof(CmiReduction)+red->numChildren*sizeof(void*));
02445 free(red);
02446 }
02447 red = newred;
02448 red->numChildren = numChildren;
02449 red->remoteData = (char**)(red+1);
02450 CpvAccess(_reduce_info)[index] = red;
02451 }
02452 return red;
02453 }
02454
02455 CmiReduction* CmiGetReduction(int id) {
02456 return CmiGetReductionCreate(id, 0);
02457 }
02458
02459 void CmiClearReduction(int id) {
02460 int index = id & ~((~0u)<<CpvAccess(_reduce_info_size));
02461 free(CpvAccess(_reduce_info)[index]);
02462 CpvAccess(_reduce_info)[index] = NULL;
02463 }
02464
02465 CmiReduction* CmiGetNextReduction(short int numChildren) {
02466 int id = CpvAccess(_reduce_seqID_global);
02467 CpvAccess(_reduce_seqID_global) += CmiReductionID_multiplier;
02468 if (id > 0xFFF0) CpvAccess(_reduce_seqID_global) = CmiReductionID_globalOffset;
02469 return CmiGetReductionCreate(id, numChildren);
02470 }
02471
02472 CmiReductionID CmiGetGlobalReduction(void) {
02473 return CpvAccess(_reduce_seqID_request)+=CmiReductionID_multiplier;
02474 }
02475
02476 CmiReductionID CmiGetDynamicReduction(void) {
02477 if (CmiMyPe() != 0) CmiAbort("Cannot call CmiGetDynamicReduction on processors other than zero!\n");
02478 return CpvAccess(_reduce_seqID_dynamic)+=CmiReductionID_multiplier;
02479 }
02480
02481 void CmiReductionHandleDynamicRequest(char *msg) {
02482 int *values = (int*)(msg+CmiMsgHeaderSizeBytes);
02483 int pe = values[0];
02484 int size = CmiMsgHeaderSizeBytes+2*sizeof(int)+values[1];
02485 values[0] = CmiGetDynamicReduction();
02486 CmiSetHandler(msg, CmiGetXHandler(msg));
02487 if (pe >= 0) {
02488 CmiSyncSendAndFree(pe, size, msg);
02489 } else {
02490 CmiSyncBroadcastAllAndFree(size, msg);
02491 }
02492 }
02493
02494 void CmiGetDynamicReductionRemote(int handlerIdx, int pe, int dataSize, void *data) {
02495 int size = CmiMsgHeaderSizeBytes+2*sizeof(int)+dataSize;
02496 char *msg = (char*)CmiAlloc(size);
02497 int *values = (int*)(msg+CmiMsgHeaderSizeBytes);
02498 values[0] = pe;
02499 values[1] = dataSize;
02500 CmiSetXHandler(msg, handlerIdx);
02501 if (dataSize) memcpy(msg+CmiMsgHeaderSizeBytes+2*sizeof(int), data, dataSize);
02502 if (CmiMyPe() == 0) {
02503 CmiReductionHandleDynamicRequest(msg);
02504 } else {
02505
02506 CmiSetHandler(msg, CpvAccess(CmiReductionDynamicRequestHandler));
02507 CmiSyncSendAndFree(0, size, msg);
02508 }
02509 }
02510
02511 void CmiSendReduce(CmiReduction *red) {
02512 void *mergedData, *msg;
02513 int msg_size;
02514 if (!red->localContributed || red->numChildren != red->numRemoteReceived) return;
02515 mergedData = red->localData;
02516 msg_size = red->localSize;
02517 if (red->numChildren > 0) {
02518 int i, offset=0;
02519 if (red->ops.pupFn != NULL) {
02520 offset = CmiReservedHeaderSize;
02521 for (i=0; i<red->numChildren; ++i) red->remoteData[i] += offset;
02522 }
02523 mergedData = (red->ops.mergeFn)(&msg_size, red->localData, (void **)red->remoteData, red->numChildren);
02524 for (i=0; i<red->numChildren; ++i) CmiFree(red->remoteData[i] - offset);
02525 }
02526
02527
02528 msg = mergedData;
02529 if (red->parent != -1) {
02530 if (red->ops.pupFn != NULL) {
02531 pup_er p = pup_new_sizer();
02532 (red->ops.pupFn)(p, mergedData);
02533 msg_size = pup_size(p) + CmiReservedHeaderSize;
02534 pup_destroy(p);
02535 msg = CmiAlloc(msg_size);
02536 p = pup_new_toMem((void*)(((char*)msg)+CmiReservedHeaderSize));
02537 (red->ops.pupFn)(p, mergedData);
02538 pup_destroy(p);
02539 if (red->ops.deleteFn != NULL) (red->ops.deleteFn)(red->localData);
02540 }
02541 CmiSetHandler(msg, CpvAccess(CmiReductionMessageHandler));
02542 CmiSetRedID(msg, red->seqID);
02543
02544 CmiSyncSendAndFree(red->parent, msg_size, msg);
02545 } else {
02546 (red->ops.destination)(msg);
02547 }
02548 CmiClearReduction(red->seqID);
02549 }
02550
02551 void *CmiReduceMergeFn_random(int *size, void *data, void** remote, int n) {
02552 return data;
02553 }
02554
02555 void CmiResetGlobalReduceSeqID(void) {
02556 CpvAccess(_reduce_seqID_global) = 0;
02557 }
02558
02559 static void CmiGlobalReduce(void *msg, int size, CmiReduceMergeFn mergeFn, CmiReduction *red) {
02560 CmiAssert(red->localContributed == 0);
02561 red->localContributed = 1;
02562 red->localData = msg;
02563 red->localSize = size;
02564 red->numChildren = CmiNumSpanTreeChildren(CmiMyPe());
02565 red->parent = CmiSpanTreeParent(CmiMyPe());
02566 red->ops.destination = (CmiHandler)CmiGetHandlerFunction(msg);
02567 red->ops.mergeFn = mergeFn;
02568 red->ops.pupFn = NULL;
02569
02570 CmiSendReduce(red);
02571 }
02572
02573 static void CmiGlobalReduceStruct(void *data, CmiReducePupFn pupFn,
02574 CmiReduceMergeFn mergeFn, CmiHandler dest,
02575 CmiReduceDeleteFn deleteFn, CmiReduction *red) {
02576 CmiAssert(red->localContributed == 0);
02577 red->localContributed = 1;
02578 red->localData = data;
02579 red->localSize = 0;
02580 red->numChildren = CmiNumSpanTreeChildren(CmiMyPe());
02581 red->parent = CmiSpanTreeParent(CmiMyPe());
02582 red->ops.destination = dest;
02583 red->ops.mergeFn = mergeFn;
02584 red->ops.pupFn = pupFn;
02585 red->ops.deleteFn = deleteFn;
02586
02587 CmiSendReduce(red);
02588 }
02589
02590 void CmiReduce(void *msg, int size, CmiReduceMergeFn mergeFn) {
02591 CmiReduction *red = CmiGetNextReduction(CmiNumSpanTreeChildren(CmiMyPe()));
02592 CmiGlobalReduce(msg, size, mergeFn, red);
02593 }
02594
02595 void CmiReduceStruct(void *data, CmiReducePupFn pupFn,
02596 CmiReduceMergeFn mergeFn, CmiHandler dest,
02597 CmiReduceDeleteFn deleteFn) {
02598 CmiReduction *red = CmiGetNextReduction(CmiNumSpanTreeChildren(CmiMyPe()));
02599 CmiGlobalReduceStruct(data, pupFn, mergeFn, dest, deleteFn, red);
02600 }
02601
02602 void CmiReduceID(void *msg, int size, CmiReduceMergeFn mergeFn, CmiReductionID id) {
02603 CmiReduction *red = CmiGetReductionCreate(id, CmiNumSpanTreeChildren(CmiMyPe()));
02604 CmiGlobalReduce(msg, size, mergeFn, red);
02605 }
02606
02607 void CmiReduceStructID(void *data, CmiReducePupFn pupFn,
02608 CmiReduceMergeFn mergeFn, CmiHandler dest,
02609 CmiReduceDeleteFn deleteFn, CmiReductionID id) {
02610 CmiReduction *red = CmiGetReductionCreate(id, CmiNumSpanTreeChildren(CmiMyPe()));
02611 CmiGlobalReduceStruct(data, pupFn, mergeFn, dest, deleteFn, red);
02612 }
02613
02614 void CmiListReduce(int npes, int *pes, void *msg, int size, CmiReduceMergeFn mergeFn, CmiReductionID id) {
02615 CmiReduction *red = CmiGetReductionCreate(id, CmiNumSpanTreeChildren(CmiMyPe()));
02616 int myPos;
02617 CmiAssert(red->localContributed == 0);
02618 red->localContributed = 1;
02619 red->localData = msg;
02620 red->localSize = size;
02621 for (myPos=0; myPos<npes; ++myPos) {
02622 if (pes[myPos] == CmiMyPe()) break;
02623 }
02624 CmiAssert(myPos < npes);
02625 red->numChildren = npes - (myPos << 2) - 1;
02626 if (red->numChildren > 4) red->numChildren = 4;
02627 if (red->numChildren < 0) red->numChildren = 0;
02628 if (myPos == 0) red->parent = -1;
02629 else red->parent = pes[(myPos - 1) >> 2];
02630 red->ops.destination = (CmiHandler)CmiGetHandlerFunction(msg);
02631 red->ops.mergeFn = mergeFn;
02632 red->ops.pupFn = NULL;
02633
02634 CmiSendReduce(red);
02635 }
02636
02637 void CmiListReduceStruct(int npes, int *pes,
02638 void *data, CmiReducePupFn pupFn,
02639 CmiReduceMergeFn mergeFn, CmiHandler dest,
02640 CmiReduceDeleteFn deleteFn, CmiReductionID id) {
02641 CmiReduction *red = CmiGetReductionCreate(id, CmiNumSpanTreeChildren(CmiMyPe()));
02642 int myPos;
02643 CmiAssert(red->localContributed == 0);
02644 red->localContributed = 1;
02645 red->localData = data;
02646 red->localSize = 0;
02647 for (myPos=0; myPos<npes; ++myPos) {
02648 if (pes[myPos] == CmiMyPe()) break;
02649 }
02650 CmiAssert(myPos < npes);
02651 red->numChildren = npes - (myPos << 2) - 1;
02652 if (red->numChildren > 4) red->numChildren = 4;
02653 if (red->numChildren < 0) red->numChildren = 0;
02654 red->parent = (myPos - 1) >> 2;
02655 if (myPos == 0) red->parent = -1;
02656 red->ops.destination = dest;
02657 red->ops.mergeFn = mergeFn;
02658 red->ops.pupFn = pupFn;
02659 red->ops.deleteFn = deleteFn;
02660 CmiSendReduce(red);
02661 }
02662
02663 void CmiGroupReduce(CmiGroup grp, void *msg, int size, CmiReduceMergeFn mergeFn, CmiReductionID id) {
02664 int npes, *pes;
02665 CmiLookupGroup(grp, &npes, &pes);
02666 CmiListReduce(npes, pes, msg, size, mergeFn, id);
02667 }
02668
02669 void CmiGroupReduceStruct(CmiGroup grp, void *data, CmiReducePupFn pupFn,
02670 CmiReduceMergeFn mergeFn, CmiHandler dest,
02671 CmiReduceDeleteFn deleteFn, CmiReductionID id) {
02672 int npes, *pes;
02673 CmiLookupGroup(grp, &npes, &pes);
02674 CmiListReduceStruct(npes, pes, data, pupFn, mergeFn, dest, deleteFn, id);
02675 }
02676
02677 void CmiNodeReduce(void *data, int size, CmiReduceMergeFn mergeFn, int redID, int numChildren, int parent) {
02678 CmiAbort("Feel free to implement CmiNodeReduce...");
02679
02680
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690 }
02691 #if 0
02692 void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int), int redID) {
02693 CmiNodeReduce(data, size, mergeFn, redID, CmiNumNodeSpanTreeChildren(CmiMyNode()),
02694 CmiNodeFirst(CmiNodeSpanTreeParent(CmiMyNode())));
02695 }
02696 void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int), int numChildren, int parent) {
02697 CmiNodeReduce(data, size, mergeFn, CmiReduceNextID(), numChildren, parent);
02698 }
02699 void CmiNodeReduce(void *data, int size, void * (*mergeFn)(void*,void**,int)) {
02700 CmiNodeReduce(data, size, mergeFn, CmiReduceNextID(), CmiNumNodeSpanTreeChildren(CmiMyNode()),
02701 CmiNodeFirst(CmiNodeSpanTreeParent(CmiMyNode())));
02702 }
02703 #endif
02704
02705 void CmiNodeReduceStruct(void *data, CmiReducePupFn pupFn,
02706 CmiReduceMergeFn mergeFn, CmiHandler dest,
02707 CmiReduceDeleteFn deleteFn) {
02708 CmiAbort("Feel free to implement CmiNodeReduceStruct...");
02709
02710
02711
02712
02713
02714
02715
02716
02717
02718
02719
02720 }
02721
02722 void CmiHandleReductionMessage(void *msg) {
02723 CmiReduction *red = CmiGetReduction(CmiGetRedID(msg));
02724 if (red->numRemoteReceived == red->numChildren) red = CmiGetReductionCreate(CmiGetRedID(msg), red->numChildren+4);
02725 red->remoteData[red->numRemoteReceived++] = (char *)msg;
02726
02727 CmiSendReduce(red);
02728
02729
02730
02731
02732 }
02733
02734 void CmiReductionsInit(void) {
02735 int i;
02736 CpvInitialize(int, CmiReductionMessageHandler);
02737 CpvAccess(CmiReductionMessageHandler) = CmiRegisterHandler((CmiHandler)CmiHandleReductionMessage);
02738 CpvInitialize(int, CmiReductionDynamicRequestHandler);
02739 CpvAccess(CmiReductionDynamicRequestHandler) = CmiRegisterHandler((CmiHandler)CmiReductionHandleDynamicRequest);
02740 CpvInitialize(CmiUInt2, _reduce_seqID_global);
02741 CpvAccess(_reduce_seqID_global) = CmiReductionID_globalOffset;
02742 CpvInitialize(CmiUInt2, _reduce_seqID_request);
02743 CpvAccess(_reduce_seqID_request) = CmiReductionID_requestOffset;
02744 CpvInitialize(CmiUInt2, _reduce_seqID_dynamic);
02745 CpvAccess(_reduce_seqID_dynamic) = CmiReductionID_dynamicOffset;
02746 CpvInitialize(int, _reduce_info_size);
02747 CpvAccess(_reduce_info_size) = 4;
02748 CpvInitialize(CmiReduction**, _reduce_info);
02749 CpvAccess(_reduce_info) = (CmiReduction **)malloc(16*sizeof(CmiReduction*));
02750 for (i=0; i<16; ++i) CpvAccess(_reduce_info)[i] = NULL;
02751 }
02752
02753
02754
02755
02756
02757
02758
02759 #if CMK_MULTICAST_DEF_USE_COMMON_CODE
02760
02761 typedef struct GroupDef_s
02762 {
02763 union {
02764 char core[CmiMsgHeaderSizeBytes];
02765 struct GroupDef_s *next;
02766 } core;
02767 CmiGroup group;
02768 int npes;
02769 int pes[1];
02770 }
02771 *GroupDef;
02772
02773 #define GROUPTAB_SIZE 101
02774
02775 CpvStaticDeclare(int, CmiGroupHandlerIndex);
02776 CpvStaticDeclare(int, CmiGroupCounter);
02777 CpvStaticDeclare(GroupDef *, CmiGroupTable);
02778
02779 void CmiGroupHandler(GroupDef def)
02780 {
02781
02782 GroupDef *table = CpvAccess(CmiGroupTable);
02783 unsigned int hashval, bucket;
02784 hashval = (def->group.id ^ def->group.pe);
02785 bucket = hashval % GROUPTAB_SIZE;
02786 def->core.next = table[bucket];
02787 table[bucket] = def;
02788 }
02789
02790 CmiGroup CmiEstablishGroup(int npes, int *pes)
02791 {
02792
02793 CmiGroup grp; GroupDef def; int len, i;
02794 grp.id = CpvAccess(CmiGroupCounter)++;
02795 grp.pe = CmiMyPe();
02796 len = sizeof(struct GroupDef_s)+(npes*sizeof(int));
02797 def = (GroupDef)CmiAlloc(len);
02798 def->group = grp;
02799 def->npes = npes;
02800 for (i=0; i<npes; i++)
02801 def->pes[i] = pes[i];
02802 CmiSetHandler(def, CpvAccess(CmiGroupHandlerIndex));
02803 CmiSyncBroadcastAllAndFree(len, def);
02804 return grp;
02805 }
02806
02807 void CmiLookupGroup(CmiGroup grp, int *npes, int **pes)
02808 {
02809 unsigned int hashval, bucket; GroupDef def;
02810 GroupDef *table = CpvAccess(CmiGroupTable);
02811 hashval = (grp.id ^ grp.pe);
02812 bucket = hashval % GROUPTAB_SIZE;
02813 for (def=table[bucket]; def; def=def->core.next) {
02814 if ((def->group.id == grp.id)&&(def->group.pe == grp.pe)) {
02815 *npes = def->npes;
02816 *pes = def->pes;
02817 return;
02818 }
02819 }
02820 *npes = 0; *pes = 0;
02821 }
02822
02823 void CmiGroupInit(void)
02824 {
02825 CpvInitialize(int, CmiGroupHandlerIndex);
02826 CpvInitialize(int, CmiGroupCounter);
02827 CpvInitialize(GroupDef *, CmiGroupTable);
02828 CpvAccess(CmiGroupHandlerIndex) = CmiRegisterHandler((CmiHandler)CmiGroupHandler);
02829 CpvAccess(CmiGroupCounter) = 0;
02830 CpvAccess(CmiGroupTable) =
02831 (GroupDef*)calloc(GROUPTAB_SIZE, sizeof(GroupDef));
02832 if (CpvAccess(CmiGroupTable) == 0)
02833 CmiAbort("Memory Allocation Error");
02834 }
02835
02836 #endif
02837
02838
02839
02840
02841
02842
02843
02844 #if CMK_MULTICAST_LIST_USE_COMMON_CODE
02845
02846 void CmiSyncListSendFn(int npes, const int *pes, int len, char *msg)
02847 {
02848 int i;
02849 #if CMK_BROADCAST_USE_CMIREFERENCE
02850 for(i=0;i<npes;i++) {
02851 if (pes[i] == CmiMyPe())
02852 CmiSyncSend(pes[i], len, msg);
02853 else {
02854 CmiReference(msg);
02855 CmiSyncSendAndFree(pes[i], len, msg);
02856 }
02857 }
02858 #else
02859 for(i=0;i<npes;i++) {
02860 CmiSyncSend(pes[i], len, msg);
02861 }
02862 #endif
02863 }
02864
02865 CmiCommHandle CmiAsyncListSendFn(int npes, const int *pes, int len, char *msg)
02866 {
02867
02868 CmiSyncListSendFn(npes, pes, len, msg);
02869 return (CmiCommHandle) 0;
02870 }
02871
02872 void CmiFreeListSendFn(int npes, const int *pes, int len, char *msg)
02873 {
02874 #if CMK_BROADCAST_USE_CMIREFERENCE
02875 if (npes == 1) {
02876 CmiSyncSendAndFree(pes[0], len, msg);
02877 return;
02878 }
02879 CmiSyncListSendFn(npes, pes, len, msg);
02880 CmiFree(msg);
02881 #else
02882 int i;
02883 for(i=0;i<npes-1;i++) {
02884 CmiSyncSend(pes[i], len, msg);
02885 }
02886 if (npes>0)
02887 CmiSyncSendAndFree(pes[npes-1], len, msg);
02888 else
02889 CmiFree(msg);
02890 #endif
02891 }
02892
02893 #endif
02894
02895 #if CMK_MULTICAST_GROUP_USE_COMMON_CODE
02896
02897 typedef struct MultiMsg_s
02898 {
02899 char core[CmiMsgHeaderSizeBytes];
02900 CmiGroup group;
02901 int pos;
02902 int origlen;
02903 }
02904 *MultiMsg;
02905
02906
02907 CpvDeclare(int, CmiMulticastHandlerIndex);
02908
02909 void CmiMulticastDeliver(MultiMsg msg)
02910 {
02911 int npes, *pes; int olen, nlen, pos, child1, child2;
02912 olen = msg->origlen;
02913 nlen = olen + sizeof(struct MultiMsg_s);
02914 CmiLookupGroup(msg->group, &npes, &pes);
02915 if (pes==0) {
02916 CmiSyncSendAndFree(CmiMyPe(), nlen, msg);
02917 return;
02918 }
02919 if (npes==0) {
02920 CmiFree(msg);
02921 return;
02922 }
02923 if (msg->pos == -1) {
02924 msg->pos=0;
02925 CmiSyncSendAndFree(pes[0], nlen, msg);
02926 return;
02927 }
02928 pos = msg->pos;
02929 child1 = ((pos+1)<<1);
02930 child2 = child1-1;
02931 if (child1 < npes) {
02932 msg->pos = child1;
02933 CmiSyncSend(pes[child1], nlen, msg);
02934 }
02935 if (child2 < npes) {
02936 msg->pos = child2;
02937 CmiSyncSend(pes[child2], nlen, msg);
02938 }
02939 if(olen < sizeof(struct MultiMsg_s)) {
02940 memcpy(msg, msg+1, olen);
02941 } else {
02942 memcpy(msg, (((char*)msg)+olen), sizeof(struct MultiMsg_s));
02943 }
02944 CmiSyncSendAndFree(CmiMyPe(), olen, msg);
02945 }
02946
02947 void CmiMulticastHandler(MultiMsg msg)
02948 {
02949 CmiMulticastDeliver(msg);
02950 }
02951
02952 void CmiSyncMulticastFn(CmiGroup grp, int len, char *msg)
02953 {
02954 int newlen; MultiMsg newmsg;
02955 newlen = len + sizeof(struct MultiMsg_s);
02956 newmsg = (MultiMsg)CmiAlloc(newlen);
02957 if(len < sizeof(struct MultiMsg_s)) {
02958 memcpy(newmsg+1, msg, len);
02959 } else {
02960 memcpy(newmsg+1, msg+sizeof(struct MultiMsg_s), len-sizeof(struct MultiMsg_s));
02961 memcpy(((char *)newmsg+len), msg, sizeof(struct MultiMsg_s));
02962 }
02963 newmsg->group = grp;
02964 newmsg->origlen = len;
02965 newmsg->pos = -1;
02966 CmiSetHandler(newmsg, CpvAccess(CmiMulticastHandlerIndex));
02967 CmiMulticastDeliver(newmsg);
02968 }
02969
02970 void CmiFreeMulticastFn(CmiGroup grp, int len, char *msg)
02971 {
02972 CmiSyncMulticastFn(grp, len, msg);
02973 CmiFree(msg);
02974 }
02975
02976 CmiCommHandle CmiAsyncMulticastFn(CmiGroup grp, int len, char *msg)
02977 {
02978 CmiError("Async Multicast not implemented.");
02979 return (CmiCommHandle) 0;
02980 }
02981
02982 void CmiMulticastInit(void)
02983 {
02984 CpvInitialize(int, CmiMulticastHandlerIndex);
02985 CpvAccess(CmiMulticastHandlerIndex) =
02986 CmiRegisterHandler((CmiHandler)CmiMulticastHandler);
02987 }
02988
02989 #else
02990 extern void CmiMulticastInit(void);
02991 #endif
02992
02993 #if CONVERSE_VERSION_SHMEM && CMK_ARENA_MALLOC
02994 extern void *arena_malloc(int size);
02995 extern void arena_free(void *blockPtr);
02996 #endif
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020
03021 void *CmiAlloc(int size)
03022 {
03023
03024 char *res;
03025
03026 #if CONVERSE_VERSION_SHMEM && CMK_ARENA_MALLOC
03027 res = (char*) arena_malloc(size+sizeof(CmiChunkHeader));
03028 #elif CMK_USE_IBVERBS | CMK_USE_IBUD
03029 res = (char *) infi_CmiAlloc(size+sizeof(CmiChunkHeader));
03030 #elif CMK_CONVERSE_UGNI || CMK_OFI
03031 res =(char *) LrtsAlloc(size, sizeof(CmiChunkHeader));
03032 #elif CONVERSE_POOL
03033 res =(char *) CmiPoolAlloc(size+sizeof(CmiChunkHeader));
03034 #elif USE_MPI_CTRLMSG_SCHEME && CMK_CONVERSE_MPI
03035 MPI_Alloc_mem(size+sizeof(CmiChunkHeader), MPI_INFO_NULL, &res);
03036 #elif CMK_SMP && CMK_BLUEGENEQ && SPECIFIC_PCQUEUE
03037 res = (char *) CmiAlloc_bgq(size+sizeof(CmiChunkHeader));
03038 #elif CMK_SMP && CMK_PPC_ATOMIC_QUEUE
03039 res = (char *) CmiAlloc_ppcq(size+sizeof(CmiChunkHeader));
03040 #else
03041 res =(char *) malloc_nomigrate(size+sizeof(CmiChunkHeader));
03042 #endif
03043
03044 _MEMCHECK(res);
03045
03046 #ifdef MEMMONITOR
03047 CpvAccess(MemoryUsage) += size+sizeof(CmiChunkHeader);
03048 CpvAccess(AllocCount)++;
03049 CpvAccess(BlocksAllocated)++;
03050 if (CpvAccess(MemoryUsage) > CpvAccess(HiWaterMark)) {
03051 CpvAccess(HiWaterMark) = CpvAccess(MemoryUsage);
03052 }
03053 if (CpvAccess(MemoryUsage) > 1.1 * CpvAccess(ReportedHiWaterMark)) {
03054 CmiPrintf("HIMEM STAT PE%d: %d Allocs, %d blocks, %lu K, Max %lu K\n",
03055 CmiMyPe(), CpvAccess(AllocCount), CpvAccess(BlocksAllocated),
03056 CpvAccess(MemoryUsage)/1024, CpvAccess(HiWaterMark)/1024);
03057 CpvAccess(ReportedHiWaterMark) = CpvAccess(MemoryUsage);
03058 }
03059 if ((CpvAccess(AllocCount) % 1000) == 0) {
03060 CmiPrintf("MEM STAT PE%d: %d Allocs, %d blocks, %lu K, Max %lu K\n",
03061 CmiMyPe(), CpvAccess(AllocCount), CpvAccess(BlocksAllocated),
03062 CpvAccess(MemoryUsage)/1024, CpvAccess(HiWaterMark)/1024);
03063 }
03064 #endif
03065
03066 res+=sizeof(CmiChunkHeader);
03067 CmiAssert((intptr_t)res % ALIGN_BYTES == 0);
03068
03069 CmiInitMsgHeader(res, size);
03070
03071 SIZEFIELD(res)=size;
03072 REFFIELDSET(res, 1);
03073 return (void *)res;
03074 }
03075
03076 void *CmiRdmaAlloc(int size) {
03077 char *res;
03078
03079 #if CMK_CONVERSE_UGNI
03080 res = (char *)LrtsRdmaAlloc(size, sizeof(CmiChunkHeader));
03081 #elif CMK_USE_IBVERBS || CMK_USE_IBUD
03082 res = (char *) infi_CmiAlloc(size+sizeof(CmiChunkHeader));
03083 #elif CMK_OFI
03084 res = (char *)LrtsAlloc(size, sizeof(CmiChunkHeader));
03085 #else
03086 res =(char *) malloc_nomigrate(size+sizeof(CmiChunkHeader));
03087 #endif
03088
03089 _MEMCHECK(res);
03090 res+=sizeof(CmiChunkHeader);
03091 CmiAssert((intptr_t)res % ALIGN_BYTES == 0);
03092
03093 CmiInitMsgHeader(res, size);
03094 SIZEFIELD(res)=size;
03095 REFFIELDSET(res, 1);
03096 return (void *)res;
03097 }
03098
03099
03101 static void *CmiAllocFindEnclosing(void *blk) {
03102 int refCount = REFFIELD(blk);
03103 while (refCount < 0) {
03104 blk = (void *)((char*)blk+refCount);
03105 refCount = REFFIELD(blk);
03106 }
03107 return blk;
03108 }
03109
03110 void CmiInitMsgHeader(void *msg, int size) {
03111 #if CMK_ONESIDED_IMPL
03112
03113 if(size >= CmiMsgHeaderSizeBytes)
03114 CMI_ZC_MSGTYPE(msg) = CMK_REG_NO_ZC_MSG;
03115 #endif
03116 }
03117
03118 int CmiGetReference(void *blk)
03119 {
03120 return REFFIELD(CmiAllocFindEnclosing(blk));
03121 }
03122
03125 void CmiReference(void *blk)
03126 {
03127 REFFIELDINC(CmiAllocFindEnclosing(blk));
03128 }
03129
03131 int CmiSize(void *blk)
03132 {
03133 return SIZEFIELD(blk);
03134 }
03135
03137 void CmiFree(void *blk)
03138 {
03139 void *parentBlk=CmiAllocFindEnclosing(blk);
03140 int refCount=REFFIELDDEC(parentBlk);
03141 #if CMK_ERROR_CHECKING
03142 if(refCount==0)
03143 CmiAbort("CmiFree reference count was zero-- is this a duplicate free?");
03144 #endif
03145 if(refCount==1) {
03146 #ifdef MEMMONITOR
03147 int size=SIZEFIELD(parentBlk);
03148 if (size > 1000000000)
03149 CmiPrintf("MEMSTAT Uh-oh -- SIZEFIELD=%d\n",size);
03150 CpvAccess(MemoryUsage) -= (size + sizeof(CmiChunkHeader));
03151 CpvAccess(BlocksAllocated)--;
03152 #endif
03153
03154 #if CONVERSE_VERSION_SHMEM && CMK_ARENA_MALLOC
03155 arena_free(BLKSTART(parentBlk));
03156 #elif CMK_USE_IBVERBS | CMK_USE_IBUD
03157
03158
03159
03160 #ifdef CMK_IBVERS_CLEAN_MULTIPLESEND
03161 if(CmiGetHandler(parentBlk)==CpvAccess(CmiMainHandlerIDP))
03162 {
03163 infi_freeMultipleSend(parentBlk);
03164 }
03165 #endif
03166 infi_CmiFree(BLKSTART(parentBlk));
03167 #elif CMK_CONVERSE_UGNI || CMK_OFI
03168 LrtsFree(BLKSTART(parentBlk));
03169 #elif CONVERSE_POOL
03170 CmiPoolFree(BLKSTART(parentBlk));
03171 #elif USE_MPI_CTRLMSG_SCHEME && CMK_CONVERSE_MPI
03172 MPI_Free_mem(parentBlk);
03173 #elif CMK_SMP && CMK_BLUEGENEQ && SPECIFIC_PCQUEUE
03174 CmiFree_bgq(BLKSTART(parentBlk));
03175 #elif CMK_SMP && CMK_PPC_ATOMIC_QUEUE
03176 CmiFree_ppcq(BLKSTART(parentBlk));
03177 #else
03178 free_nomigrate(BLKSTART(parentBlk));
03179 #endif
03180 }
03181 }
03182
03183 void CmiRdmaFree(void *blk)
03184 {
03185 void *parentBlk=CmiAllocFindEnclosing(blk);
03186 int refCount=REFFIELDDEC(parentBlk);
03187 #if CMK_ERROR_CHECKING
03188 if(refCount==0)
03189 CmiAbort("CmiRdmaFree reference count was zero-- is this a duplicate free?");
03190 #endif
03191 if(refCount==1) {
03192 #ifdef MEMMONITOR
03193 int size=SIZEFIELD(parentBlk);
03194 if (size > 1000000000)
03195 CmiPrintf("MEMSTAT Uh-oh -- SIZEFIELD=%d\n",size);
03196 CpvAccess(MemoryUsage) -= (size + sizeof(CmiChunkHeader));
03197 CpvAccess(BlocksAllocated)--;
03198 #endif
03199
03200 #if CMK_CONVERSE_UGNI
03201 LrtsRdmaFree(BLKSTART(parentBlk));
03202 #elif CMK_USE_IBVERBS || CMK_USE_IBUD
03203 infi_CmiFree(BLKSTART(parentBlk));
03204 #elif CMK_OFI
03205 LrtsFree(BLKSTART(parentBlk));
03206 #else
03207 free_nomigrate(BLKSTART(parentBlk));
03208 #endif
03209 }
03210 }
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223 #define CMI_TMP_BUF_MAX 16*1024
03224
03225 typedef struct {
03226 char *buf;
03227 int cur;
03228 int max;
03229 } CmiTmpBuf_t;
03230 CpvDeclare(CmiTmpBuf_t,CmiTmpBuf);
03231
03232 static void CmiTmpSetup(CmiTmpBuf_t *b) {
03233 b->buf=(char *)malloc(CMI_TMP_BUF_MAX);
03234 b->cur=0;
03235 b->max=CMI_TMP_BUF_MAX;
03236 }
03237
03238 void *CmiTmpAlloc(int size) {
03239 if (!CpvInitialized(CmiTmpBuf)) {
03240 return malloc(size);
03241 }
03242 else {
03243 CmiTmpBuf_t *b=&CpvAccess(CmiTmpBuf);
03244 void *t;
03245 if (b->cur+size>b->max) {
03246 if (b->max==0)
03247 CmiTmpSetup(b);
03248 else
03249 return malloc(size);
03250 }
03251 t=b->buf+b->cur;
03252 b->cur+=size;
03253 return t;
03254 }
03255 }
03256 void CmiTmpFree(void *t) {
03257 if (!CpvInitialized(CmiTmpBuf)) {
03258 free(t);
03259 }
03260 else {
03261 CmiTmpBuf_t *b=&CpvAccess(CmiTmpBuf);
03262
03263 int cur=((const char *)t)-b->buf;
03264 if (cur<0 || cur>b->max) {
03265 free(t);
03266 } else {
03267 b->cur=cur;
03268 }
03269 }
03270 }
03271
03272 void CmiTmpInit(char **argv) {
03273 CpvInitialize(CmiTmpBuf_t,CmiTmpBuf);
03274
03275 CmiTmpSetup(&CpvAccess(CmiTmpBuf));
03276 }
03277
03278
03279
03280
03281
03282
03283 #ifdef _WIN32
03284
03285 #include <windows.h>
03286
03287 void CmiMkdir(const char *dirName) {
03288 CreateDirectory(dirName,NULL);
03289 }
03290
03291 int CmiGetPageSize(void)
03292 {
03293 SYSTEM_INFO system_info;
03294 GetSystemInfo(&system_info);
03295 return system_info.dwPageSize;
03296 }
03297 #else
03298
03299 #include <unistd.h>
03300 #include <sys/stat.h>
03301 #include <sys/types.h>
03302
03303 void CmiMkdir(const char *dirName) {
03304 mkdir(dirName,0777);
03305 }
03306
03307 int CmiGetPageSize(void)
03308 {
03309 #if CMK_HAS_GETPAGESIZE
03310 return getpagesize();
03311 #else
03312 return CMK_MEMORY_PAGESIZE;
03313 #endif
03314 }
03315
03316 #endif
03317
03318
03319
03320
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341
03342 static int roundUpSize(unsigned int s) {
03343 return (int)((s+sizeof(double)-1)&~(sizeof(double)-1));
03344 }
03345
03346
03347
03348 static int paddingSize(unsigned int s) {
03349 return roundUpSize(s)-s;
03350 }
03351
03352
03353 typedef struct {
03354 char convHeader[CmiMsgHeaderSizeBytes];
03355 int nMessages;
03356 double pad;
03357 } CmiMultipleSendHeader;
03358
03359 #if CMK_USE_IBVERBS | CMK_USE_IBUD
03360
03361
03362 void infi_freeMultipleSend(void *msgWhole)
03363 {
03364 int len=((CmiMultipleSendHeader *)msgWhole)->nMessages;
03365 double pad=((CmiMultipleSendHeader *)msgWhole)->pad;
03366 int offset=sizeof(CmiMultipleSendHeader);
03367 int m;
03368 void *thisMsg=NULL;
03369 if (pad != 1234567.89) return;
03370 for(m=0;m<len;m++)
03371 {
03372
03373
03374
03375 infiCmiChunkHeader *ch = (infiCmiChunkHeader *)((char *)msgWhole + offset);
03376 char *msg = (char *)msgWhole + offset + sizeof(infiCmiChunkHeader);
03377 int msgSize=ch->chunkHeader.size;
03378 infi_unregAndFreeMeta(ch->metaData);
03379 offset+= sizeof(infiCmiChunkHeader) + msgSize;
03380 }
03381 }
03382 #endif
03383
03384
03385 static void _CmiMultipleSend(unsigned int destPE, int len, int sizes[], char *msgComps[], int immed)
03386 {
03387 CmiMultipleSendHeader header;
03388 int m;
03389
03390 CmiInitMsgHeader(header.convHeader, sizeof(CmiMultipleSendHeader));
03391 #if CMK_USE_IBVERBS
03392 infiCmiChunkHeader *msgHdr;
03393 #else
03394 CmiChunkHeader *msgHdr;
03395 #endif
03396
03397 double pad = 0;
03398 int vecLen;
03399 int *vecSizes;
03400 char **vecPtrs;
03401 int vec;
03402
03403 #if CMK_USE_IBVERBS
03404 msgHdr = (infiCmiChunkHeader *)CmiTmpAlloc(len * sizeof(infiCmiChunkHeader));
03405 #else
03406 msgHdr = (CmiChunkHeader *)CmiTmpAlloc(len * sizeof(CmiChunkHeader));
03407 #endif
03408
03409
03410 vecLen=1+3*len;
03411 vecSizes = (int *)CmiTmpAlloc(vecLen * sizeof(int));
03412 vecPtrs = (char **)CmiTmpAlloc(vecLen * sizeof(char *));
03413 vec=0;
03414
03415
03416 header.nMessages=len;
03417 CmiSetHandler(&header, CpvAccess(CmiMainHandlerIDP));
03418 header.pad = 1234567.89;
03419 #if CMK_IMMEDIATE_MSG
03420 if (immed) CmiBecomeImmediate(&header);
03421 #endif
03422 vecSizes[vec]=sizeof(header); vecPtrs[vec]=(char *)&header;
03423 vec++;
03424
03425
03426
03427
03428 for (m=0;m<len;m++) {
03429 #if CMK_USE_IBVERBS
03430 msgHdr[m].chunkHeader.size=roundUpSize(sizes[m]);
03431 msgHdr[m].chunkHeader.setRef(0);
03432 msgHdr[m].metaData=NULL;
03433 #else
03434 msgHdr[m].size=roundUpSize(sizes[m]);
03435 msgHdr[m].setRef(0);
03436 #endif
03437
03438
03439 #if CMK_USE_IBVERBS
03440 vecSizes[vec]=sizeof(infiCmiChunkHeader);
03441 #else
03442 vecSizes[vec]=sizeof(CmiChunkHeader);
03443 #endif
03444 vecPtrs[vec]=(char *)&msgHdr[m];
03445 vec++;
03446
03447
03448 vecSizes[vec]=sizes[m]; vecPtrs[vec]=msgComps[m];
03449 vec++;
03450
03451
03452 vecSizes[vec]=paddingSize(sizes[m]); vecPtrs[vec]=(char *)&pad;
03453 vec++;
03454 }
03455 CmiAssert(vec==vecLen);
03456
03457 CmiSyncVectorSend(destPE, vecLen, vecSizes, vecPtrs);
03458
03459 CmiTmpFree(vecPtrs);
03460 CmiTmpFree(vecSizes);
03461 CmiTmpFree(msgHdr);
03462 }
03463
03464 void CmiMultipleSend(unsigned int destPE, int len, int sizes[], char *msgComps[])
03465 {
03466 _CmiMultipleSend(destPE, len, sizes, msgComps, 0);
03467 }
03468
03469 void CmiMultipleIsend(unsigned int destPE, int len, int sizes[], char *msgComps[])
03470 {
03471 _CmiMultipleSend(destPE, len, sizes, msgComps, 1);
03472 }
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483 static void CmiMultiMsgHandler(char *msgWhole);
03484
03485 void CmiInitMultipleSend(void)
03486 {
03487 CpvInitialize(int,CmiMainHandlerIDP);
03488 CpvAccess(CmiMainHandlerIDP) =
03489 CmiRegisterHandler((CmiHandler)CmiMultiMsgHandler);
03490 }
03491
03492
03493
03494
03495
03496
03497
03498 static void CmiMultiMsgHandler(char *msgWhole)
03499 {
03500 int len=((CmiMultipleSendHeader *)msgWhole)->nMessages;
03501 int offset=sizeof(CmiMultipleSendHeader);
03502 int m;
03503 for (m=0;m<len;m++) {
03504 #if CMK_USE_IBVERBS
03505 infiCmiChunkHeader *ch=(infiCmiChunkHeader *)(msgWhole+offset);
03506 char *msg=(msgWhole+offset+sizeof(infiCmiChunkHeader));
03507 int msgSize=ch->chunkHeader.size;
03508 ch->chunkHeader.setRef(msgWhole-msg);
03509 ch->metaData = registerMultiSendMesg(msg,msgSize);
03510 #else
03511 CmiChunkHeader *ch=(CmiChunkHeader *)(msgWhole+offset);
03512 char *msg=(msgWhole+offset+sizeof(CmiChunkHeader));
03513 int msgSize=ch->size;
03514 ch->setRef(msgWhole-msg);
03515 #endif
03516
03517 CmiReference(msg);
03518 CmiSyncSendAndFree(CmiMyPe(), msgSize, msg);
03519 #if CMK_USE_IBVERBS
03520 offset+= sizeof(infiCmiChunkHeader) + msgSize;
03521 #else
03522 offset+= sizeof(CmiChunkHeader) + msgSize;
03523 #endif
03524 }
03525
03526
03527 CmiFree(msgWhole);
03528 }
03529
03530
03531
03532
03533
03534 int HypercubeGetBcastDestinations(int mype, int total_pes, int k, int *dest_pes) {
03535 int num_pes = 0;
03536 for ( ; k>=0; --k) {
03537
03538 dest_pes[num_pes] = mype ^ (1<<k);
03539 if (dest_pes[num_pes] >= total_pes) {
03540
03541 dest_pes[num_pes] &= (~0u)<<k;
03542
03543
03544
03545 if (total_pes>dest_pes[num_pes]) dest_pes[num_pes] += (mype - (mype & ((~0u)<<k))) % (total_pes - dest_pes[num_pes]);
03546 }
03547 if (dest_pes[num_pes] < total_pes) {
03548
03549 ++num_pes;
03550 }
03551 }
03552 return num_pes;
03553 }
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564 int _immediateLock = 0;
03565 int _immediateFlag = 0;
03566
03567 CpvDeclare(int, CmiImmediateMsgHandlerIdx);
03568
03569
03570 static void CmiImmediateMsgHandler(char *msg)
03571 {
03572 CmiSetHandler(msg, CmiGetXHandler(msg));
03573 CmiHandleMessage(msg);
03574 }
03575
03576 void CmiInitImmediateMsg(void)
03577 {
03578 CpvInitialize(int,CmiImmediateMsgHandlerIdx);
03579 CpvAccess(CmiImmediateMsgHandlerIdx) =
03580 CmiRegisterHandler((CmiHandler)CmiImmediateMsgHandler);
03581 }
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593 typedef struct {
03594 int idle_timeout;
03595 int is_idle;
03596 int call_count;
03597 } cmi_cpu_idlerec;
03598
03599 static void on_timeout(cmi_cpu_idlerec *rec,double curWallTime)
03600 {
03601 rec->call_count--;
03602 if(rec->call_count==0 && rec->is_idle==1) {
03603 CmiError("Idle time on PE %d exceeded specified timeout.\n", CmiMyPe());
03604 CmiAbort("Exiting.\n");
03605 }
03606 }
03607 static void on_idle(cmi_cpu_idlerec *rec,double curWallTime)
03608 {
03609 CcdCallFnAfter((CcdVoidFn)on_timeout, rec, rec->idle_timeout);
03610 rec->call_count++;
03611 rec->is_idle = 1;
03612 }
03613 static void on_busy(cmi_cpu_idlerec *rec,double curWallTime)
03614 {
03615 rec->is_idle = 0;
03616 }
03617 static void CIdleTimeoutInit(char **argv)
03618 {
03619 int idle_timeout=0;
03620 CmiGetArgIntDesc(argv,"+idle-timeout",&idle_timeout,"Abort if idle for this many seconds");
03621 if(idle_timeout != 0) {
03622 cmi_cpu_idlerec *rec=(cmi_cpu_idlerec *)malloc(sizeof(cmi_cpu_idlerec));
03623 _MEMCHECK(rec);
03624 rec->idle_timeout=idle_timeout*1000;
03625 rec->is_idle=0;
03626 rec->call_count=0;
03627 CcdCallOnCondition(CcdPROCESSOR_BEGIN_IDLE, (CcdVoidFn)on_idle, rec);
03628 CcdCallOnCondition(CcdPROCESSOR_BEGIN_BUSY, (CcdVoidFn)on_busy, rec);
03629 }
03630 }
03631
03632
03633
03634
03635
03636
03637
03638 void CrnInit(void);
03639 void CmiIsomallocInit(char **argv);
03640 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
03641 void CmiIOInit(char **argv);
03642 #endif
03643
03644
03645 void CmiInitCPUAffinityUtil(void);
03646
03647 static void CmiProcessPriority(char **argv)
03648 {
03649 int dummy, nicelevel=-100;
03650 CmiGetArgIntDesc(argv,"+nice",&nicelevel,"Set the process priority level");
03651
03652 while (CmiGetArgIntDesc(argv,"+nice",&dummy,"Set the process priority level"));
03653
03654 if (CmiMyRank() == 0 && nicelevel != -100) {
03655 #ifndef _WIN32
03656 if (0!=setpriority(PRIO_PROCESS, 0, nicelevel)) {
03657 CmiPrintf("[%d] setpriority failed with value %d. \n", CmiMyPe(), nicelevel);
03658 perror("setpriority");
03659 CmiAbort("setpriority failed.");
03660 }
03661 else
03662 CmiPrintf("[%d] Charm++: setpriority %d\n", CmiMyPe(), nicelevel);
03663 #else
03664 HANDLE hProcess = GetCurrentProcess();
03665 DWORD dwPriorityClass = NORMAL_PRIORITY_CLASS;
03666 const char *prio_str = "NORMAL_PRIORITY_CLASS";
03667 BOOL status;
03668
03669
03670
03671
03672
03673
03674
03675
03676 if (0) ;
03677 #ifdef BELOW_NORMAL_PRIORITY_CLASS
03678 else if (nicelevel<10 && nicelevel>0) {
03679 dwPriorityClass = BELOW_NORMAL_PRIORITY_CLASS;
03680 prio_str = "BELOW_NORMAL_PRIORITY_CLASS";
03681 }
03682 #endif
03683 else if (nicelevel>0) {
03684 dwPriorityClass = IDLE_PRIORITY_CLASS;
03685 prio_str = "IDLE_PRIORITY_CLASS";
03686 }
03687 else if (nicelevel<=-20) {
03688 dwPriorityClass = REALTIME_PRIORITY_CLASS;
03689 prio_str = "REALTIME_PRIORITY_CLASS";
03690 }
03691 #ifdef ABOVE_NORMAL_PRIORITY_CLASS
03692 else if (nicelevel>-10 && nicelevel<0) {
03693 dwPriorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
03694 prio_str = "ABOVE_NORMAL_PRIORITY_CLASS";
03695 }
03696 #endif
03697 else if (nicelevel<0) {
03698 dwPriorityClass = HIGH_PRIORITY_CLASS;
03699 prio_str = "HIGH_PRIORITY_CLASS";
03700 }
03701 status = SetPriorityClass(hProcess, dwPriorityClass);
03702 if (!status) {
03703 int err=GetLastError();
03704 CmiPrintf("SetPriorityClass failed errno=%d, WSAerr=%d\n",errno, err);
03705 CmiAbort("SetPriorityClass failed.");
03706 }
03707 else
03708 CmiPrintf("[%d] Charm++: setpriority %s\n", CmiMyPe(), prio_str);
03709 #endif
03710 }
03711 }
03712
03713 void CommunicationServerInit(void)
03714 {
03715 #if CMK_IMMEDIATE_MSG
03716 #if CMI_QD
03717 CQdCpvInit();
03718 #endif
03719 CpvInitialize(int,CmiImmediateMsgHandlerIdx);
03720 #endif
03721 }
03722
03723
03724 static int testEndian(void)
03725 {
03726 int test=0x1c;
03727 unsigned char *c=(unsigned char *)&test;
03728 if (c[sizeof(int)-1]==0x1c)
03729
03730 return 1;
03731 if (c[0]==0x1c)
03732
03733 return 0;
03734 return -2;
03735 }
03736
03737 int CmiEndianness(void)
03738 {
03739 static int _cmi_endianness = -1;
03740 if (_cmi_endianness == -1) _cmi_endianness = testEndian();
03741 CmiAssert(_cmi_endianness != -2);
03742 return _cmi_endianness;
03743 }
03744
03745 #if CMK_USE_TSAN
03746
03747
03748 static void checkTSanOptions(void)
03749 {
03750 char *env = getenv("TSAN_OPTIONS");
03751
03752 if (!env ||
03753 !strstr(env, "log_path=") ||
03754 strstr(env, "log_path=stdout") ||
03755 strstr(env, "log_path=stderr")) {
03756 CmiAbort("TSAN output must be redirected to disk.\n"
03757 "Run this program with TSAN_OPTIONS=\"log_path=filename\"");
03758 }
03759 }
03760 #endif
03761
03762 #if CMK_CCS_AVAILABLE
03763 extern int ccsRunning;
03764 int ccsRunning;
03765 #endif
03766
03767 extern int quietModeRequested;
03768 int quietModeRequested;
03769 extern int quietMode;
03770 int quietMode;
03771 CmiSpanningTreeInfo* _topoTree = NULL;
03772
03798 void ConverseCommonInit(char **argv)
03799 {
03800 CpvInitialize(int, _urgentSend);
03801 CpvAccess(_urgentSend) = 0;
03802 CpvInitialize(int,interopExitFlag);
03803 CpvAccess(interopExitFlag) = 0;
03804
03805 CpvInitialize(int,_curRestartPhase);
03806 CpvAccess(_curRestartPhase)=1;
03807 CmiArgInit(argv);
03808 CmiMemoryInit(argv);
03809 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
03810 CmiIOInit(argv);
03811 #endif
03812 if (CmiMyPe() == 0)
03813 CmiPrintf("Converse/Charm++ Commit ID: %s\n", CmiCommitID);
03814
03815 CpvInitialize(int, cmiMyPeIdle);
03816 CpvAccess(cmiMyPeIdle) = 0;
03817
03818 #if CONVERSE_POOL
03819 CmiPoolAllocInit(30);
03820 #endif
03821 CmiTmpInit(argv);
03822 CmiTimerInit(argv);
03823 CstatsInit(argv);
03824 CmiInitCPUAffinityUtil();
03825
03826 CcdModuleInit(argv);
03827 CmiHandlerInit();
03828 CmiReductionsInit();
03829 CIdleTimeoutInit(argv);
03830
03831 #if CMK_SHARED_VARS_POSIX_THREADS_SMP
03832 if(CmiGetArgFlagDesc(argv, "+CmiSpinOnIdle", "Force the runtime system to spin on message reception when idle, rather than sleeping")) {
03833 if(CmiMyRank() == 0) _Cmi_forceSpinOnIdle = 1;
03834 }
03835 if(CmiGetArgFlagDesc(argv, "+CmiSleepOnIdle", "Force the runtime system to sleep when idle, rather than spinning on message reception")) {
03836 if(CmiMyRank() == 0) _Cmi_sleepOnIdle = 1;
03837 }
03838 if(CmiGetArgFlagDesc(argv,"+CmiNoProcForComThread","Is there an extra processor for the communication thread on each node(only for netlrts-smp-*) ?")){
03839 if (CmiMyPe() == 0) {
03840 CmiPrintf("Charm++> Note: The option +CmiNoProcForComThread has been superseded by +CmiSleepOnIdle\n");
03841 }
03842 if(CmiMyRank() == 0) _Cmi_sleepOnIdle=1;
03843 }
03844 if (_Cmi_sleepOnIdle && _Cmi_forceSpinOnIdle) {
03845 if(CmiMyRank() == 0) CmiAbort("The option +CmiSpinOnIdle is mutually exclusive with the options +CmiSleepOnIdle and +CmiNoProcForComThread");
03846 }
03847 #endif
03848
03849 #if CMK_TRACE_ENABLED
03850 traceInit(argv);
03851
03852 #endif
03853 CmiProcessPriority(argv);
03854
03855 #if CMK_USE_TSAN
03856 checkTSanOptions();
03857 #endif
03858
03859 CmiPersistentInit();
03860 CmiIsomallocInit(argv);
03861
03862 CmiOnesidedDirectInit();
03863 CmiDeliversInit();
03864 CsdInit(argv);
03865 #if CMK_CCS_AVAILABLE
03866 ccsRunning = 0;
03867 CcsInit(argv);
03868 #endif
03869 CpdInit();
03870 CthSchedInit();
03871 CmiGroupInit();
03872 CmiMulticastInit();
03873 CmiInitMultipleSend();
03874 #if CMI_QD
03875 CQdInit();
03876 #endif
03877
03878 CrnInit();
03879 CmiInitImmediateMsg();
03880 CldModuleInit(argv);
03881
03882 #if CMK_CELL
03883 void CmiInitCell();
03884 CmiInitCell();
03885 #endif
03886
03887
03888
03889
03890
03891
03892 #if CMK_BIGSIM_CHARM
03893
03894 initQd(argv);
03895 #endif
03896 }
03897
03898 void ConverseCommonExit(void)
03899 {
03900 CcsImpl_kill();
03901
03902 #if CMK_TRACE_ENABLED
03903 traceClose();
03904
03905 #endif
03906
03907 #if CMI_IO_BUFFER_EXPLICIT
03908 CmiFlush(stdout);
03909 #endif
03910
03911 #if CMK_CELL
03912 CloseOffloadAPI();
03913 #endif
03914
03915 #if CMK_CUDA
03916
03917 if(CmiMyRank() < CmiMyNodeSize()) {
03918 CmiNodeBarrier();
03919 }
03920 if (CmiMyRank() == 0) {
03921 exitHybridAPI();
03922 }
03923 #endif
03924 seedBalancerExit();
03925 EmergencyExit();
03926 }
03927
03928
03929 #if CMK_CELL != 0
03930
03931 extern void register_accel_spe_funcs(void);
03932
03933 void CmiInitCell(void)
03934 {
03935
03936
03937 char fileNameBuf[64];
03938 sprintf(fileNameBuf, "speTiming.%d", CmiMyPe());
03939
03940 InitOffloadAPI(offloadCallback, NULL, NULL, fileNameBuf);
03941
03942
03943 CcdCallOnConditionKeep(CcdPROCESSOR_STILL_IDLE,
03944 (CcdVoidFn) OffloadAPIProgress, NULL);
03945
03946
03947 register_accel_spe_funcs();
03948 }
03949
03950 #include "cell-api.c"
03951
03952 #endif
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
03964 void CmiIOInit(char **argv) {
03965 CpvInitialize(int, expIOFlushFlag);
03966 #if CMI_IO_BUFFER_EXPLICIT
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976
03977 CpvInitialize(char*, explicitIOBuffer);
03978 CpvInitialize(int, expIOBufferSize);
03979 if (!CmiGetArgIntDesc(argv,"+io_buffer_size", &CpvAccess(expIOBufferSize),
03980 "Explicit IO Buffer Size")) {
03981 CpvAccess(expIOBufferSize) = DEFAULT_IO_BUFFER_SIZE;
03982 }
03983 if (CpvAccess(expIOBufferSize) <= 0) {
03984 CpvAccess(expIOBufferSize) = DEFAULT_IO_BUFFER_SIZE;
03985 }
03986 CpvAccess(explicitIOBuffer) = (char*)CmiAlloc(CpvAccess(expIOBufferSize)*
03987 sizeof(char));
03988 if (setvbuf(stdout, CpvAccess(explicitIOBuffer), _IOFBF,
03989 CpvAccess(expIOBufferSize))) {
03990 CmiAbort("Explicit IO Buffering failed\n");
03991 }
03992 #endif
03993 #if CMI_IO_FLUSH_USER
03994
03995
03996 CpvAccess(expIOFlushFlag) = !CmiGetArgFlagDesc(argv,"+io_flush_system",
03997 "System Controls IO Flush");
03998 #else
03999
04000
04001 CpvAccess(expIOFlushFlag) = CmiGetArgFlagDesc(argv,"+io_flush_user",
04002 "User Controls IO Flush");
04003 #endif
04004 }
04005 #endif
04006
04007 #if ! CMK_CMIPRINTF_IS_A_BUILTIN
04008
04009 void CmiPrintf(const char *format, ...)
04010 {
04011 if (quietMode) return;
04012 CpdSystemEnter();
04013 {
04014 va_list args;
04015 va_start(args,format);
04016 vfprintf(stdout,format, args);
04017 if (CpvInitialized(expIOFlushFlag) && !CpvAccess(expIOFlushFlag)) {
04018 CmiFlush(stdout);
04019 }
04020 va_end(args);
04021 #if CMK_CCS_AVAILABLE && CMK_CMIPRINTF_IS_A_BUILTIN
04022 if (CpvAccess(cmiArgDebugFlag)) {
04023 va_start(args,format);
04024 print_node0(format, args);
04025 va_end(args);
04026 }
04027 #endif
04028 }
04029 CpdSystemExit();
04030 }
04031
04032 void CmiError(const char *format, ...)
04033 {
04034 CpdSystemEnter();
04035 {
04036 va_list args;
04037 va_start(args,format);
04038 vfprintf(stderr,format, args);
04039 CmiFlush(stderr);
04040 va_end(args);
04041 #if CMK_CCS_AVAILABLE && CMK_CMIPRINTF_IS_A_BUILTIN
04042 if (CpvAccess(cmiArgDebugFlag)) {
04043 va_start(args,format);
04044 print_node0(format, args);
04045 va_end(args);
04046 }
04047 #endif
04048 }
04049 CpdSystemExit();
04050 }
04051
04052 #endif
04053
04054 void __cmi_assert(const char *errmsg)
04055 {
04056 CmiError("[%d] %s\n", CmiMyPe(), errmsg);
04057 CmiAbort(errmsg);
04058 }
04059
04060 char *CmiCopyMsg(char *msg, int len)
04061 {
04062 char *copy = (char *)CmiAlloc(len);
04063 _MEMCHECK(copy);
04064 memcpy(copy, msg, len);
04065 return copy;
04066 }
04067
04068 unsigned char computeCheckSum(unsigned char *data, int len)
04069 {
04070 int i;
04071 unsigned char ret = 0;
04072 for (i=0; i<len; i++) ret ^= (unsigned char)data[i];
04073 return ret;
04074 }
04075
04076
04077 int _BgOutOfCoreFlag=0;
04078 int _BgInOutOfCoreMode=0;
04079
04080 #if !CMK_HAS_LOG2
04081 unsigned int CmiILog2(unsigned int val) {
04082 unsigned int log = 0u;
04083 if ( val != 0u ) {
04084 while ( val > (1u<<log) ) { log++; }
04085 }
04086 return log;
04087 }
04088 double CmiLog2(double x) {
04089 return log(x)/log(2);
04090 }
04091 #endif
04092
04093
04094 int CmiMyRank_(void)
04095 {
04096 return CmiMyRank();
04097 }
04098
04099 double CmiReadSize(const char *str)
04100 {
04101 double val;
04102 if (strpbrk(str,"Gg")) {
04103
04104
04105 val = atof(str);
04106 val *= 1024ll*1024*1024;
04107 }
04108 else if (strpbrk(str,"Mm")) {
04109 val = atof(str);
04110 val *= 1024*1024;
04111 }
04112 else if (strpbrk(str,"Kk")) {
04113 val = atof(str);
04114 val *= 1024;
04115 }
04116 else {
04117 val = atof(str);
04118 }
04119 return val;
04120 }
04121
04122 void CmiSetPeHelpsOtherThreads(int input) {
04123 CpvAccess(isHelperOn) = input;
04124 CmiMemoryWriteFence();
04125 }
04126