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