00001
00002
00003
00004
00005
00006 #include "tcharm_impl.h"
00007 #include "tcharm.h"
00008 #include <ctype.h>
00009
00010 #if 0
00011
00012 # define DBG(x) ckout<<"["<<thisIndex<<","<<CkMyPe()<<"] TCHARM> "<<x<<endl;
00013 # define DBGX(x) ckout<<"PE("<<CkMyPe()<<") TCHARM> "<<x<<endl;
00014 #else
00015
00016 # define DBG(x)
00017 # define DBGX(x)
00018 #endif
00019
00020 CtvDeclare(TCharm *,_curTCharm);
00021
00022 static int lastNumChunks=0;
00023
00024 class TCharmTraceLibList {
00025 enum {maxLibs=20,maxLibNameLen=15};
00026
00027 int curLibs;
00028 char libNames[maxLibs][maxLibNameLen];
00029 int checkIfTracing(const char *lib) const
00030 {
00031 for (int i=0;i<curLibs;i++)
00032 if (0==strcmp(lib,libNames[i]))
00033 return 1;
00034 return 0;
00035 }
00036 public:
00037 TCharmTraceLibList() {curLibs=0;}
00038 void addTracing(const char *lib)
00039 {
00040 CkPrintf("TCHARM> Will trace calls to library %s\n",lib);
00041 int i;
00042 for (i=0;0!=*lib;i++,lib++)
00043 libNames[curLibs][i]=tolower(*lib);
00044 libNames[curLibs][i]=0;
00045
00046 if (checkIfTracing(libNames[curLibs])) return;
00047 curLibs++;
00048 }
00049 inline int isTracing(const char *lib) const {
00050 if (curLibs==0) return 0;
00051 else return checkIfTracing(lib);
00052 }
00053 };
00054 static TCharmTraceLibList tcharm_tracelibs;
00055 static int tcharm_nomig=0, tcharm_nothreads=0;
00056 static int tcharm_stacksize=1*1024*1024;
00057 static int tcharm_initted=0;
00058 CkpvDeclare(int, mapCreated);
00059 static CkGroupID mapID;
00060 static char* mapping = NULL;
00061
00062 void TCharm::nodeInit(void)
00063 {
00064 }
00065
00066 void TCharm::procInit(void)
00067 {
00068 CtvInitialize(TCharm *,_curTCharm);
00069 CtvAccess(_curTCharm)=NULL;
00070 tcharm_initted=1;
00071 CtgInit();
00072
00073 CkpvInitialize(int, mapCreated);
00074 CkpvAccess(mapCreated) = 0;
00075
00076
00077 char **argv=CkGetArgv();
00078 tcharm_nomig=CmiGetArgFlagDesc(argv,"+tcharm_nomig","Disable migration support (debugging)");
00079 tcharm_nothreads=CmiGetArgFlagDesc(argv,"+tcharm_nothread","Disable thread support (debugging)");
00080 tcharm_nothreads|=CmiGetArgFlagDesc(argv,"+tcharm_nothreads",NULL);
00081 char *traceLibName=NULL;
00082 while (CmiGetArgStringDesc(argv,"+tcharm_trace",&traceLibName,"Print each call to this library"))
00083 tcharm_tracelibs.addTracing(traceLibName);
00084 CmiGetArgIntDesc(argv,"+tcharm_stacksize",&tcharm_stacksize,"Set the thread stack size (default 1MB)");
00085 if (CkMyPe()!=0) {
00086 int ignored;
00087 while (CmiGetArgIntDesc(argv,"-vp",&ignored,NULL)) {}
00088 while (CmiGetArgIntDesc(argv,"+vp",&ignored,NULL)) {}
00089 }
00090 if (CkMyPe()==0) {
00091 if (tcharm_nomig) CmiPrintf("TCHARM> Disabling migration support, for debugging\n");
00092 if (tcharm_nothreads) CmiPrintf("TCHARM> Disabling thread support, for debugging\n");
00093 }
00094 if (CkpvAccess(mapCreated)==0) {
00095 if (0!=CmiGetArgString(argv, "+mapping", &mapping)){
00096 }
00097 CkpvAccess(mapCreated)=1;
00098 }
00099 }
00100
00101 void TCHARM_Api_trace(const char *routineName,const char *libraryName)
00102 {
00103 if (!tcharm_tracelibs.isTracing(libraryName)) return;
00104 TCharm *tc=CtvAccess(_curTCharm);
00105 char where[100];
00106 if (tc==NULL) sprintf(where,"[serial context on %d]",CkMyPe());
00107 else sprintf(where,"[%p> vp %d, p %d]",(void *)tc,tc->getElement(),CkMyPe());
00108 CmiPrintf("%s Called routine %s\n",where,routineName);
00109 CmiPrintStackTrace(1);
00110 CmiPrintf("\n");
00111 }
00112
00113 #if CMK_TCHARM_FNPTR_HACK
00114 CDECL void AMPI_threadstart(void *data);
00115 #endif
00116
00117 static void startTCharmThread(TCharmInitMsg *msg)
00118 {
00119 DBGX("thread started");
00120 TCharm::activateThread();
00121 typedef void (*threadFn_t)(void *);
00122 #if CMK_TCHARM_FNPTR_HACK
00123 ((threadFn_t)AMPI_threadstart)(msg->data);
00124 #else
00125 ((threadFn_t)msg->threadFn)(msg->data);
00126 #endif
00127 TCharm::deactivateThread();
00128 CtvAccess(_curTCharm)->done();
00129 }
00130
00131 TCharm::TCharm(TCharmInitMsg *initMsg_)
00132 {
00133 initMsg=initMsg_;
00134 initMsg->opts.sanityCheck();
00135 timeOffset=0.0;
00136 threadGlobals=CtgCreate();
00137 if (tcharm_nothreads)
00138 {
00139 tid=CthSelf();
00140 }
00141 else
00142 {
00143 if (tcharm_nomig) {
00144 tid=CthCreate((CthVoidFn)startTCharmThread,initMsg,initMsg->opts.stackSize);
00145 } else {
00146 tid=CthCreateMigratable((CthVoidFn)startTCharmThread,initMsg,initMsg->opts.stackSize);
00147 }
00148 #if CMK_BLUEGENE_CHARM
00149 BgAttach(tid);
00150 #endif
00151 }
00152 CtvAccessOther(tid,_curTCharm)=this;
00153 isStopped=true;
00154 resumeAfterMigration=false;
00155
00156 AsyncEvacuate(CmiTrue);
00157 skipResume=false;
00158 exitWhenDone=initMsg->opts.exitWhenDone;
00159 threadInfo.tProxy=CProxy_TCharm(thisArrayID);
00160 threadInfo.thisElement=thisIndex;
00161 threadInfo.numElements=initMsg->numElements;
00162 if (CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC))
00163 heapBlocks=CmiIsomallocBlockListNew();
00164 else
00165 heapBlocks=0;
00166 nUd=0;
00167 usesAtSync=CmiTrue;
00168 run();
00169 }
00170
00171 TCharm::TCharm(CkMigrateMessage *msg)
00172 :CBase_TCharm(msg)
00173 {
00174 initMsg=NULL;
00175 tid=NULL;
00176 threadGlobals=NULL;
00177 threadInfo.tProxy=CProxy_TCharm(thisArrayID);
00178 AsyncEvacuate(CmiTrue);
00179 heapBlocks=0;
00180 }
00181
00182 void checkPupMismatch(PUP::er &p,int expected,const char *where)
00183 {
00184 int v=expected;
00185 p|v;
00186 if (v!=expected) {
00187 CkError("FATAL ERROR> Mismatch %s pup routine\n",where);
00188 CkAbort("FATAL ERROR: Pup direction mismatch");
00189 }
00190 }
00191
00192 void TCharm::pup(PUP::er &p) {
00193
00194 ArrayElement1D::pup(p);
00195
00196 checkPupMismatch(p,5134,"before TCHARM");
00197 p(isStopped); p(resumeAfterMigration); p(exitWhenDone); p(skipResume);
00198 p(threadInfo.thisElement);
00199 p(threadInfo.numElements);
00200
00201 if (sema.size()>0)
00202 CkAbort("TCharm::pup> Cannot migrate with unconsumed semaphores!\n");
00203
00204 #ifndef CMK_OPTIMIZE
00205 DBG("Packing thread");
00206 if (!isStopped && !CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC)){
00207 CkAbort("Cannot pup a running thread. You must suspend before migrating.\n");
00208 }
00209 if (tcharm_nomig) CkAbort("Cannot migrate with the +tcharm_nomig option!\n");
00210 #endif
00211
00212
00213
00214
00215 PUP::seekBlock s(p,2);
00216
00217 if (p.isUnpacking())
00218 {
00219 s.seek(1);
00220 pupThread(p);
00221
00222 double packTime;
00223 p(packTime);
00224 timeOffset=packTime-CkWallTimer();
00225 }
00226
00227
00228
00229 CtvAccess(_curTCharm)=this;
00230 activateThread();
00231
00232 s.seek(0);
00233 checkPupMismatch(p,5135,"before TCHARM user data");
00234 p(nUd);
00235 for(int i=0;i<nUd;i++) {
00236 if (p.isUnpacking()) ud[i].update(tid);
00237 ud[i].pup(p);
00238 }
00239 checkPupMismatch(p,5137,"after TCHARM_Register user data");
00240
00241 if (CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC))
00242 deactivateThread();
00243 p|sud;
00244 checkPupMismatch(p,5138,"after TCHARM_Global user data");
00245
00246
00247 if (!CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC))
00248 deactivateThread();
00249 CtvAccess(_curTCharm)=NULL;
00250
00251 if (!p.isUnpacking())
00252 {
00253 s.seek(1);
00254 pupThread(p);
00255
00256 double packTime=CkWallTimer()+timeOffset;
00257 p(packTime);
00258 }
00259
00260 s.endBlock();
00261 checkPupMismatch(p,5140,"after TCHARM");
00262 }
00263
00264
00265 void TCharm::pupThread(PUP::er &pc) {
00266 pup_er p=(pup_er)&pc;
00267 checkPupMismatch(pc,5138,"before TCHARM thread");
00268 tid = CthPup(p, tid);
00269 if (pc.isUnpacking()) {
00270 CtvAccessOther(tid,_curTCharm)=this;
00271 #if CMK_BLUEGENE_CHARM
00272 BgAttach(tid);
00273 #endif
00274 }
00275 if (CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC))
00276 CmiIsomallocBlockListPup(p,&heapBlocks);
00277 threadGlobals=CtgPup(p,threadGlobals);
00278 checkPupMismatch(pc,5139,"after TCHARM thread");
00279 }
00280
00281
00282 void TCharm::UserData::pup(PUP::er &p)
00283 {
00284 pup_er pext=(pup_er)(&p);
00285 p(mode);
00286 switch(mode) {
00287 case 'c': {
00288
00289 p(pos);
00290
00291 p((char*)&cfn, sizeof(TCHARM_Pup_fn));
00292 char *data = CthPointer(t, pos);
00293 if (cfn) cfn(pext,data);
00294 } break;
00295 case 'g': {
00296 if (CmiMemoryIs(CMI_MEMORY_IS_ISOMALLOC))
00297 {
00298
00299 p(pos);
00300 }
00301 else if (p.isUnpacking())
00302 pos=0;
00303
00304
00305 p((char*)&gfn, sizeof(TCHARM_Pup_global_fn));
00306 if (gfn) gfn(pext);
00307 } break;
00308 default:
00309 break;
00310 };
00311 }
00312
00313 TCharm::~TCharm()
00314 {
00315 if (heapBlocks) CmiIsomallocBlockListDelete(heapBlocks);
00316 CthFree(tid);
00317 CtgFree(threadGlobals);
00318 delete initMsg;
00319 }
00320
00321 void TCharm::migrateTo(int destPE) {
00322 if (destPE==CkMyPe()) return;
00323
00324 thisProxy[thisIndex].migrateDelayed(destPE);
00325
00326 suspend();
00327 }
00328 void TCharm::migrateDelayed(int destPE) {
00329 migrateMe(destPE);
00330 }
00331 void TCharm::ckJustMigrated(void) {
00332 ArrayElement::ckJustMigrated();
00333 if (resumeAfterMigration) {
00334 resumeAfterMigration=false;
00335 resume();
00336 }
00337 }
00338
00339
00340
00341
00342
00343
00344 void TCharm::ckAboutToMigrate(void){
00345 ArrayElement::ckAboutToMigrate();
00346 resumeAfterMigration = true;
00347 isStopped = true;
00348
00349 }
00350
00351
00352 void TCharm::clear()
00353 {
00354 if (heapBlocks) CmiIsomallocBlockListDelete(heapBlocks);
00355 CthFree(tid);
00356 delete initMsg;
00357 }
00358
00359
00360 int TCharm::add(const TCharm::UserData &d)
00361 {
00362 if (nUd>=maxUserData)
00363 CkAbort("TCharm: Registered too many user data fields!\n");
00364 int nu=nUd++;
00365 ud[nu]=d;
00366 return nu;
00367 }
00368 void *TCharm::lookupUserData(int i) {
00369 if (i<0 || i>=nUd)
00370 CkAbort("Bad user data index passed to TCharmGetUserdata!\n");
00371 return ud[i].getData();
00372 }
00373
00374
00375 void TCharm::run(void)
00376 {
00377 DBG("TCharm::run()");
00378 if (tcharm_nothreads) {
00379 startTCharmThread(initMsg);
00380 }
00381 else
00382 start();
00383 }
00384
00385
00386 void TCharm::stop(void)
00387 {
00388 #ifndef CMK_OPTIMIZE
00389 if (tid != CthSelf())
00390 CkAbort("Called TCharm::stop from outside TCharm thread!\n");
00391 if (tcharm_nothreads)
00392 CkAbort("Cannot make blocking calls using +tcharm_nothreads!\n");
00393 #endif
00394 stopTiming();
00395 isStopped=true;
00396 DBG("thread suspended");
00397 CthSuspend();
00398
00399
00400
00401
00402
00403
00404 TCharm *dis=TCharm::get();
00405 dis->isStopped=false;
00406 dis->startTiming();
00407
00408 }
00409
00410
00411 void TCharm::start(void)
00412 {
00413
00414 isStopped=false;
00415 DBG("thread resuming soon");
00416 CthAwaken(tid);
00417 }
00418
00419
00420 void TCharm::schedule(void) {
00421 DBG("thread schedule");
00422 start();
00423 stop();
00424 }
00425
00426
00427 void TCharm::migrate(void)
00428 {
00429 #if CMK_LBDB_ON
00430 DBG("going to sync");
00431 AtSync();
00432 stop();
00433 #else
00434 DBG("skipping sync, because there is no load balancer");
00435 #endif
00436 }
00437
00438
00439 void TCharm::evacuate(){
00440
00441
00442
00443
00444 if(CpvAccess(startedEvac)){
00445 int nextPE = getNextPE(CkArrayIndex1D(thisIndex));
00446
00447 CcdCallFnAfter((CcdVoidFn)CkEmmigrateElement, (void *)myRec, 1);
00448 suspend();
00449 return;
00450 }
00451 return;
00452
00453 }
00454
00455
00456 void TCharm::async_migrate(void)
00457 {
00458 #if CMK_LBDB_ON
00459 DBG("going to sync at async mode");
00460 skipResume = true;
00461 ReadyMigrate(false);
00462 AtSync(0);
00463 schedule();
00464
00465 #else
00466 DBG("skipping sync, because there is no load balancer");
00467 #endif
00468 }
00469
00470
00471
00472
00473
00474 void TCharm::allow_migrate(void)
00475 {
00476 #if CMK_LBDB_ON
00477
00478 int nextPe = MigrateToPe();
00479 if (nextPe != -1) {
00480 migrateTo(nextPe);
00481 }
00482 #else
00483 DBG("skipping sync, because there is no load balancer");
00484 #endif
00485 }
00486
00487
00488 void TCharm::ResumeFromSync(void)
00489 {
00490 if (!skipResume) start();
00491 }
00492
00493
00494
00495 void TCharmClient1D::ckJustMigrated(void) {
00496 ArrayElement1D::ckJustMigrated();
00497 findThread();
00498 tcharmClientInit();
00499 }
00500
00501 void TCharmClient1D::pup(PUP::er &p) {
00502 ArrayElement1D::pup(p);
00503 p|threadProxy;
00504 }
00505
00506 CkArrayID TCHARM_Get_threads(void) {
00507 TCHARMAPI("TCHARM_Get_threads");
00508 return TCharm::get()->getProxy();
00509 }
00510
00511
00512
00513
00514 int vals[2]={0,1};
00515
00516
00517 void TCharm::barrier(void) {
00518
00519 CkCallback cb(index_t::atBarrier(0), thisProxy[0]);
00520 contribute(sizeof(vals),&vals,CkReduction::sum_int,cb);
00521 #if CMK_BLUEGENE_CHARM
00522 void *curLog;
00523 _TRACE_BG_TLINE_END(&curLog);
00524 TRACE_BG_AMPI_BREAK(NULL, "TCharm_Barrier_START", NULL, 0);
00525 #endif
00526 stop();
00527 #if CMK_BLUEGENE_CHARM
00528 _TRACE_BG_SET_INFO(NULL, "TCHARM_Barrier_END", &curLog, 1);
00529 #endif
00530 }
00531
00532
00533 void TCharm::atBarrier(CkReductionMsg *m) {
00534 DBGX("clients all at barrier");
00535 delete m;
00536 thisProxy.start();
00537 }
00538
00539
00540 void TCharm::done(void) {
00541 DBG("TCharm thread "<<thisIndex<<" done")
00542 if (exitWhenDone) {
00543
00544 CkCallback cb(index_t::atExit(0), thisProxy[0]);
00545 contribute(sizeof(vals),&vals,CkReduction::sum_int,cb);
00546 }
00547 stop();
00548 }
00549
00550 void TCharm::atExit(CkReductionMsg *m) {
00551 DBGX("TCharm::atExit> exiting");
00552 delete m;
00553 CkExit();
00554 }
00555
00556
00557
00558
00559
00560 static TCHARM_Fallback_setup_fn g_fallbackSetup=NULL;
00561 void TCHARM_Set_fallback_setup(TCHARM_Fallback_setup_fn f)
00562 {
00563 g_fallbackSetup=f;
00564 }
00565 void TCHARM_Call_fallback_setup(void) {
00566 if (g_fallbackSetup)
00567 (g_fallbackSetup)();
00568 else
00569 CkAbort("TCHARM: Unexpected fallback setup--missing TCHARM_User_setup routine?");
00570 }
00571
00572
00573
00574
00575
00576
00577
00578 CDECL int TCHARM_Get_num_chunks(void)
00579 {
00580 TCHARMAPI("TCHARM_Get_num_chunks");
00581 if (CkMyPe()!=0) CkAbort("TCHARM_Get_num_chunks should only be called on PE 0 during setup!");
00582 int nChunks=CkNumPes();
00583 char **argv=CkGetArgv();
00584 CmiGetArgIntDesc(argv,"-vp",&nChunks,"Set the total number of virtual processors");
00585 CmiGetArgIntDesc(argv,"+vp",&nChunks,NULL);
00586 lastNumChunks=nChunks;
00587 return nChunks;
00588 }
00589 FDECL int FTN_NAME(TCHARM_GET_NUM_CHUNKS,tcharm_get_num_chunks)(void)
00590 {
00591 return TCHARM_Get_num_chunks();
00592 }
00593
00594
00595 TCHARM_Thread_options::TCHARM_Thread_options(int doDefault)
00596 {
00597 stackSize=0;
00598 exitWhenDone=0;
00599 }
00600 void TCHARM_Thread_options::sanityCheck(void) {
00601 if (stackSize<=0) stackSize=tcharm_stacksize;
00602 }
00603
00604
00605 TCHARM_Thread_options g_tcharmOptions(1);
00606
00607
00608 CDECL void TCHARM_Set_stack_size(int newStackSize)
00609 {
00610 TCHARMAPI("TCHARM_Set_stack_size");
00611 g_tcharmOptions.stackSize=newStackSize;
00612 }
00613 FDECL void FTN_NAME(TCHARM_SET_STACK_SIZE,tcharm_set_stack_size)
00614 (int *newSize)
00615 { TCHARM_Set_stack_size(*newSize); }
00616
00617 CDECL void TCHARM_Set_exit(void) { g_tcharmOptions.exitWhenDone=1; }
00618
00619
00620 CDECL void TCHARM_Create(int nThreads,
00621 TCHARM_Thread_start_fn threadFn)
00622 {
00623 TCHARMAPI("TCHARM_Create");
00624 TCHARM_Create_data(nThreads,
00625 (TCHARM_Thread_data_start_fn)threadFn,NULL,0);
00626 }
00627 FDECL void FTN_NAME(TCHARM_CREATE,tcharm_create)
00628 (int *nThreads,TCHARM_Thread_start_fn threadFn)
00629 { TCHARM_Create(*nThreads,threadFn); }
00630
00631 static CProxy_TCharm TCHARM_Build_threads(TCharmInitMsg *msg);
00632
00633
00634 CDECL void TCHARM_Create_data(int nThreads,
00635 TCHARM_Thread_data_start_fn threadFn,
00636 void *threadData,int threadDataLen)
00637 {
00638 TCHARMAPI("TCHARM_Create_data");
00639 TCharmInitMsg *msg=new (threadDataLen,0) TCharmInitMsg(
00640 (CthVoidFn)threadFn,g_tcharmOptions);
00641 msg->numElements=nThreads;
00642 memcpy(msg->data,threadData,threadDataLen);
00643 TCHARM_Build_threads(msg);
00644
00645
00646 g_tcharmOptions=TCHARM_Thread_options(1);
00647 }
00648
00649 FDECL void FTN_NAME(TCHARM_CREATE_DATA,tcharm_create_data)
00650 (int *nThreads,
00651 TCHARM_Thread_data_start_fn threadFn,
00652 void *threadData,int *threadDataLen)
00653 { TCHARM_Create_data(*nThreads,threadFn,threadData,*threadDataLen); }
00654
00655 CkGroupID CkCreatePropMap(void);
00656
00657 static CProxy_TCharm TCHARM_Build_threads(TCharmInitMsg *msg)
00658 {
00659 CkArrayOptions opts(msg->numElements);
00660 CkAssert(CkpvAccess(mapCreated)==1);
00661 if(mapping==NULL){
00662 mapID=CkCreatePropMap();
00663 }else if(0==strcmp(mapping,"BLOCK_MAP")){
00664 mapID=CProxy_BlockMap::ckNew();
00665 }else if(0==strcmp(mapping,"RR_MAP")){
00666 mapID=CProxy_RRMap::ckNew();
00667 }else{
00668 mapID=CkCreatePropMap();
00669 }
00670 opts.setMap(mapID);
00671 int nElem=msg->numElements;
00672 return CProxy_TCharm::ckNew(msg,opts);
00673 }
00674
00675
00676 CkArrayOptions TCHARM_Attach_start(CkArrayID *retTCharmArray,int *retNumElts)
00677 {
00678 TCharm *tc=TCharm::get();
00679 if (!tc)
00680 CkAbort("You must call TCHARM initialization routines from a TCHARM thread!");
00681 int nElts=tc->getNumElements();
00682 if (retNumElts!=NULL) *retNumElts=nElts;
00683 *retTCharmArray=tc->getProxy();
00684 CkArrayOptions opts(nElts);
00685 opts.bindTo(tc->getProxy());
00686 return opts;
00687 }
00688
00689 void TCHARM_Suspend(void) {
00690 TCharm *tc=TCharm::get();
00691 tc->suspend();
00692 }
00693
00694
00695
00696
00697 CDECL int TCHARM_Element(void)
00698 {
00699 TCHARMAPI("TCHARM_Element");
00700 return TCharm::get()->getElement();
00701 }
00702 CDECL int TCHARM_Num_elements(void)
00703 {
00704 TCHARMAPI("TCHARM_Num_elements");
00705 return TCharm::get()->getNumElements();
00706 }
00707
00708 FDECL int FTN_NAME(TCHARM_ELEMENT,tcharm_element)(void)
00709 { return TCHARM_Element();}
00710 FDECL int FTN_NAME(TCHARM_NUM_ELEMENTS,tcharm_num_elements)(void)
00711 { return TCHARM_Num_elements();}
00712
00713
00714 static void checkAddress(void *data)
00715 {
00716 if (tcharm_nomig||tcharm_nothreads) return;
00717 if (CmiThreadIs(CMI_THREAD_IS_ALIAS)||CmiThreadIs(CMI_THREAD_IS_STACKCOPY)) return;
00718 if (!CmiIsomallocInRange(data))
00719 CkAbort("The UserData you register must be allocated on the stack!\n");
00720 }
00721
00722
00723 CDECL int TCHARM_Register(void *data,TCHARM_Pup_fn pfn)
00724 {
00725 TCHARMAPI("TCHARM_Register");
00726 checkAddress(data);
00727 return TCharm::get()->add(TCharm::UserData(pfn,TCharm::get()->getThread(),data));
00728 }
00729 FDECL int FTN_NAME(TCHARM_REGISTER,tcharm_register)
00730 (void *data,TCHARM_Pup_fn pfn)
00731 {
00732 TCHARMAPI("TCHARM_Register");
00733 checkAddress(data);
00734 return TCharm::get()->add(TCharm::UserData(pfn,TCharm::get()->getThread(),data));
00735 }
00736
00737 CDECL void *TCHARM_Get_userdata(int id)
00738 {
00739 TCHARMAPI("TCHARM_Get_userdata");
00740 return TCharm::get()->lookupUserData(id);
00741 }
00742 FDECL void *FTN_NAME(TCHARM_GET_USERDATA,tcharm_get_userdata)(int *id)
00743 { return TCHARM_Get_userdata(*id); }
00744
00745
00746 CDECL void TCHARM_Set_global(int globalID,void *new_value,TCHARM_Pup_global_fn pup_or_NULL)
00747 {
00748 TCHARMAPI("TCHARM_Set_global");
00749 TCharm *tc=TCharm::get();
00750 if (tc->sud.length()<=globalID)
00751 {
00752 int newLen=2*globalID;
00753 tc->sud.resize(newLen);
00754 }
00755 tc->sud[globalID]=TCharm::UserData(pup_or_NULL,tc->getThread(),new_value);
00756 }
00757 CDECL void *TCHARM_Get_global(int globalID)
00758 {
00759
00760
00761 CkVec<TCharm::UserData> &v=TCharm::get()->sud;
00762 if (v.length()<=globalID) return NULL;
00763 return v[globalID].getData();
00764 }
00765
00766 CDECL void TCHARM_Migrate(void)
00767 {
00768 TCHARMAPI("TCHARM_Migrate");
00769 TCharm::get()->migrate();
00770 }
00771 FORTRAN_AS_C(TCHARM_MIGRATE,TCHARM_Migrate,tcharm_migrate,(void),())
00772
00773 CDECL void TCHARM_Async_Migrate(void)
00774 {
00775 TCHARMAPI("TCHARM_Async_Migrate");
00776 TCharm::get()->async_migrate();
00777 }
00778 FORTRAN_AS_C(TCHARM_ASYNC_MIGRATE,TCHARM_Async_Migrate,tcharm_async_migrate,(void),())
00779
00780 CDECL void TCHARM_Allow_Migrate(void)
00781 {
00782 TCHARMAPI("TCHARM_Allow_Migrate");
00783 TCharm::get()->allow_migrate();
00784 }
00785 FORTRAN_AS_C(TCHARM_ALLOW_MIGRATE,TCHARM_Allow_Migrate,tcharm_allow_migrate,(void),())
00786
00787 CDECL void TCHARM_Migrate_to(int destPE)
00788 {
00789 TCHARMAPI("TCHARM_Migrate_to");
00790 TCharm::get()->migrateTo(destPE);
00791 }
00792
00793 CDECL void TCHARM_Evacuate()
00794 {
00795 TCHARMAPI("TCHARM_Migrate_to");
00796 TCharm::get()->evacuate();
00797 }
00798
00799 FORTRAN_AS_C(TCHARM_MIGRATE_TO,TCHARM_Migrate_to,tcharm_migrate_to,
00800 (int *destPE),(*destPE))
00801
00802 CDECL void TCHARM_Yield(void)
00803 {
00804 TCHARMAPI("TCHARM_Yield");
00805 TCharm::get()->schedule();
00806 }
00807 FORTRAN_AS_C(TCHARM_YIELD,TCHARM_Yield,tcharm_yield,(void),())
00808
00809 CDECL void TCHARM_Barrier(void)
00810 {
00811 TCHARMAPI("TCHARM_Barrier");
00812 TCharm::get()->barrier();
00813 }
00814 FORTRAN_AS_C(TCHARM_BARRIER,TCHARM_Barrier,tcharm_barrier,(void),())
00815
00816 CDECL void TCHARM_Done(void)
00817 {
00818 TCHARMAPI("TCHARM_Done");
00819 TCharm *c=TCharm::getNULL();
00820 if (!c) CkExit();
00821 else c->done();
00822 }
00823 FORTRAN_AS_C(TCHARM_DONE,TCHARM_Done,tcharm_done,(void),())
00824
00825
00826 CDECL double TCHARM_Wall_timer(void)
00827 {
00828 TCHARMAPI("TCHARM_Wall_timer");
00829 TCharm *c=TCharm::getNULL();
00830 if(!c) return CkWallTimer();
00831 else {
00832 return CkWallTimer()+c->getTimeOffset();
00833 }
00834 }
00835
00836 #if 1
00837
00838
00839
00840 FDECL int FTN_NAME(TCHARM_IARGC,tcharm_iargc)(void) {
00841 TCHARMAPI("tcharm_iargc");
00842 return CkGetArgc()-1;
00843 }
00844
00845 FDECL void FTN_NAME(TCHARM_GETARG,tcharm_getarg)
00846 (int *i_p,char *dest,int destLen)
00847 {
00848 TCHARMAPI("tcharm_getarg");
00849 int i=*i_p;
00850 if (i<0) CkAbort("tcharm_getarg called with negative argument!");
00851 if (i>=CkGetArgc()) CkAbort("tcharm_getarg called with argument > iargc!");
00852 const char *src=CkGetArgv()[i];
00853 strcpy(dest,src);
00854 for (i=strlen(dest);i<destLen;i++) dest[i]=' ';
00855 }
00856
00857 #endif
00858
00859
00860 extern void _initCharm(int argc, char **argv);
00861 CDECL void TCHARM_Init(int *argc,char ***argv) {
00862 if (!tcharm_initted) {
00863 ConverseInit(*argc, *argv, (CmiStartFn) _initCharm,1,1);
00864 _initCharm(*argc,*argv);
00865 }
00866 }
00867
00868 FDECL void FTN_NAME(TCHARM_INIT,tcharm_init)(void)
00869 {
00870 int argc=1;
00871 char *argv_sto[2]={"foo",NULL};
00872 char **argv=argv_sto;
00873 TCHARM_Init(&argc,&argv);
00874 }
00875
00876
00877
00878
00879
00880
00881
00882
00883
00885 TCharm::TCharmSemaphore *TCharm::findSema(int id) {
00886 for (int s=0;s<sema.size();s++)
00887 if (sema[s].id==id)
00888 return &sema[s];
00889 sema.push_back(TCharmSemaphore(id));
00890 return &sema[sema.size()-1];
00891 }
00893 void TCharm::freeSema(TCharmSemaphore *doomed) {
00894 int id=doomed->id;
00895 for (int s=0;s<sema.size();s++)
00896 if (sema[s].id==id) {
00897 sema[s]=sema[sema.length()-1];
00898 sema.length()--;
00899 return;
00900 }
00901 CkAbort("Tried to free nonexistent TCharm semaphore");
00902 }
00903
00905 TCharm::TCharmSemaphore *TCharm::getSema(int id) {
00906 TCharmSemaphore *s=findSema(id);
00907 if (s->data==NULL)
00908 {
00909