00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __CHARM_TCHARM_IMPL_H
00011 #define __CHARM_TCHARM_IMPL_H
00012
00013 #include "pup.h"
00014 #include "pup_c.h"
00015 #include "charm-api.h"
00016 #include "tcharmc.h"
00017 #include "cklists.h"
00018 #include "memory-isomalloc.h"
00019
00020 #include "cmitls.h"
00021
00022 #if 0
00023
00024 # define DBG(x) ckout<<"["<<thisIndex<<","<<CkMyPe()<<"] TCHARM> "<<x<<endl;
00025 # define DBGX(x) ckout<<"PE("<<CkMyPe()<<") TCHARM> "<<x<<endl;
00026 #else
00027
00028 # define DBG(x)
00029 # define DBGX(x)
00030 #endif
00031
00032 class TCharmTraceLibList;
00033
00035 class callSystemStruct {
00036 public:
00037 const char *cmd;
00038 int *ret;
00039 };
00040 PUPbytes(callSystemStruct)
00041
00042
00043 #include "tcharm.decl.h"
00044
00045 class TCharm;
00046
00047
00048
00049
00050 class TCHARM_Thread_options {
00051 public:
00052 int stackSize;
00053 bool exitWhenDone;
00054
00055 TCHARM_Thread_options(int doDefault);
00056 TCHARM_Thread_options() {}
00057
00058 void sanityCheck(void);
00059 };
00060
00061 class TCharmInitMsg : public CMessage_TCharmInitMsg {
00062 public:
00063
00064
00065 int threadFn;
00066
00067 TCHARM_Thread_options opts;
00068
00069 int numElements;
00070
00071 char *data;
00072
00073 TCharmInitMsg(int threadFn_,const TCHARM_Thread_options &opts_)
00074 :threadFn(threadFn_), opts(opts_) {}
00075 };
00076
00077 extern bool tcharm_nothreads;
00078
00079
00080 CtvExtern(TCharm *,_curTCharm);
00081
00082 class TCharm: public CBase_TCharm
00083 {
00084 private:
00085 friend class TCharmAPIRoutine;
00086
00087 CthThread tid;
00088 CmiIsomallocBlockList *heapBlocks;
00089 #if CMI_SWAPGLOBALS
00090 CtgGlobals threadGlobals;
00091 #endif
00092
00093
00094
00095
00096 bool isStopped, exitWhenDone, isSelfDone, asyncMigrate;
00097
00098
00099 class ThreadInfo {
00100 public:
00101 CProxy_TCharm tProxy;
00102 int thisElement;
00103 int numElements;
00104 };
00105 ThreadInfo threadInfo;
00106
00107 TCharmInitMsg *initMsg;
00108 double timeOffset;
00109
00110 public:
00111
00112 class UserData {
00113 CthThread t;
00114 size_t pos;
00115 char mode;
00116 TCHARM_Pup_fn cfn;
00117 TCHARM_Pup_global_fn gfn;
00118 public:
00119 UserData(int i=0) {pos=0; mode='?'; cfn=NULL; gfn=NULL;}
00120 UserData(TCHARM_Pup_fn cfn_,CthThread t_,void *p)
00121 {cfn=cfn_; t=t_; pos=CthStackOffset(t, (char *)p); mode='c';}
00122 UserData(TCHARM_Pup_global_fn gfn_,CthThread t_,void *p)
00123 {gfn=gfn_; t=t_; pos=CthStackOffset(t, (char *)p); mode='g';}
00124 inline void *getData() const {return pos==0?NULL:CthPointer(t, pos);}
00125 void pup(PUP::er &p);
00126 void update(CthThread t_) { t=t_; }
00127 friend inline void operator|(PUP::er &p,UserData &d) {d.pup(p);}
00128 };
00129
00130 CkVec<UserData> sud;
00131
00132
00133 class TCharmSemaphore {
00134 public:
00135 int id;
00136 void *data;
00137 CthThread thread;
00138
00139 TCharmSemaphore() { id=-1; data=NULL; thread=NULL; }
00140 TCharmSemaphore(int id_) { id=id_; data=NULL; thread=NULL; }
00141 };
00143 CkVec<TCharmSemaphore> sema;
00144
00145 private:
00146
00147 enum {maxUserData=16};
00148 int nUd;
00149 UserData ud[maxUserData];
00150
00151 void pupThread(PUP::er &p);
00152 void ResumeFromSync();
00153
00154 public:
00155 TCharm(TCharmInitMsg *initMsg);
00156 TCharm(CkMigrateMessage *);
00157 ~TCharm();
00158
00159 virtual void ckJustMigrated();
00160 virtual void ckJustRestored();
00161 virtual void ckAboutToMigrate();
00162
00163 void migrateDelayed(int destPE);
00164 void atBarrier();
00165 void atExit(CkReductionMsg *msg) noexcept;
00166 void clear();
00167
00168
00169 virtual void pup(PUP::er &p);
00170
00171 TCharmSemaphore *findSema(int id);
00172 TCharmSemaphore *getSema(int id);
00173 void freeSema(TCharmSemaphore *);
00174
00177 void semaPut(int id,void *data);
00178
00180 void *semaPeek(int id);
00181
00184 void *semaGets(int id);
00185
00189 void *semaGet(int id);
00190
00191
00192 static void nodeInit();
00193 static void procInit();
00194
00195
00196 void run() noexcept;
00197
00198 inline double getTimeOffset() const noexcept { return timeOffset; }
00199
00200
00201
00202 void barrier() noexcept;
00203
00204
00205 void migrateTo(int destPE) noexcept;
00206
00207 #if CMK_FAULT_EVAC
00208 void evacuate() noexcept;
00209 #endif
00210
00211
00212 void done(int exitcode) noexcept;
00213
00214
00215 int add(const UserData &d) noexcept;
00216 void *lookupUserData(int ud) noexcept;
00217
00218 inline static TCharm *get() noexcept {
00219 TCharm *c=getNULL();
00220 #if CMK_ERROR_CHECKING
00221 if (!c) ::CkAbort("TCharm has not been initialized!\n");
00222 #endif
00223 return c;
00224 }
00225 inline static TCharm *getNULL() noexcept {return CtvAccess(_curTCharm);}
00226 inline CthThread getThread() noexcept {return tid;}
00227 inline const CProxy_TCharm &getProxy() const noexcept {return threadInfo.tProxy;}
00228 inline int getElement() const noexcept {return threadInfo.thisElement;}
00229 inline int getNumElements() const noexcept {return threadInfo.numElements;}
00230
00231
00232 inline void stopTiming() noexcept {ckStopTiming();}
00233 inline void startTiming() noexcept {ckStartTiming();}
00234
00235
00236 void schedule() noexcept {
00237 DBG("thread schedule");
00238 start();
00239 stop();
00240 }
00241
00242
00243
00244 void stop() noexcept {
00245 #if CMK_ERROR_CHECKING
00246 if (tid != CthSelf())
00247 CkAbort("Called TCharm::stop from outside TCharm thread!\n");
00248 if (tcharm_nothreads)
00249 CkAbort("Cannot make blocking calls using +tcharm_nothreads!\n");
00250 #endif
00251 stopTiming();
00252 isStopped=true;
00253 DBG("thread suspended");
00254
00255 CthSuspend();
00256
00257
00258
00259
00260 TCharm *dis=TCharm::get();
00261 dis->isStopped=false;
00262 dis->startTiming();
00263 }
00264
00265 void start() noexcept {
00266 isStopped=false;
00267 DBG("thread resuming soon");
00268 CthAwaken(tid);
00269 }
00270
00271
00272 inline void suspend() noexcept {stop();}
00273 inline void resume() noexcept {
00274
00275 if (isStopped){
00276 start();
00277 }
00278
00279
00280
00281 }
00282
00283
00284 void migrate() noexcept;
00285 void async_migrate() noexcept;
00286 void allow_migrate();
00287
00288
00289 static void activateThread(void) noexcept {
00290
00291
00292
00293 TCharm *tc=CtvAccess(_curTCharm);
00294 if (tc!=NULL) {
00295 if (tc->heapBlocks)
00296 CmiIsomallocBlockListActivate(tc->heapBlocks);
00297 #if CMI_SWAPGLOBALS
00298 if (tc->threadGlobals)
00299 CtgInstall(tc->threadGlobals);
00300 #endif
00301 }
00302 }
00303
00304 static void deactivateThread() noexcept {
00305 CmiIsomallocBlockListActivate(NULL);
00306 #if CMI_SWAPGLOBALS
00307 CtgInstall(NULL);
00308 #endif
00309 }
00310
00312 int system(const char *cmd);
00313 void callSystem(const callSystemStruct &s);
00314
00315 inline CthThread getTid() { return tid; }
00316 };
00317
00318 void TCHARM_Api_trace(const char *routineName, const char *libraryName) noexcept;
00319
00320 #if CMK_TRACE_ENABLED
00321 typedef std::unordered_map<std::string, int> funcmap;
00322 CsvExtern(funcmap*, tcharm_funcmap);
00323
00324 static
00325 int tcharm_routineNametoID(char const *routineName) noexcept
00326 {
00327 funcmap::iterator it;
00328 it = CsvAccess(tcharm_funcmap)->find(routineName);
00329
00330 if (it != CsvAccess(tcharm_funcmap)->end())
00331 return it->second;
00332
00333 return -1;
00334 }
00335 #endif
00336
00337
00338
00339
00340
00341
00342 class TCharmAPIRoutine {
00343 private:
00344 bool doIsomalloc;
00345 bool doSwapglobals;
00346 tlsseg_t oldtlsseg;
00347 #if CMK_TRACE_ENABLED
00348 double start;
00349 int tcharm_routineID;
00350 #endif
00351 #if CMK_BIGSIM_CHARM
00352 void *callEvent;
00353 int pe;
00354 #endif
00355
00356 public:
00357
00358 #if CMK_TRACE_ENABLED
00359 TCharmAPIRoutine(const char *routineName, const char *libraryName) noexcept {
00360 #else
00361 TCharmAPIRoutine() noexcept {
00362 #endif
00363 #if CMK_BIGSIM_CHARM
00364
00365
00366 _TRACE_BG_TLINE_END(&callEvent);
00367 _TRACE_BG_END_EXECUTE(0);
00368 pe = CmiMyPe();
00369 _TRACE_BG_BEGIN_EXECUTE_NOMSG(routineName, &callEvent, 0);
00370 #endif
00371 #if CMK_TRACE_ENABLED
00372 start = CmiWallTimer();
00373 tcharm_routineID = tcharm_routineNametoID(routineName);
00374 #endif
00375
00376 doIsomalloc = (CmiIsomallocBlockListCurrent() != NULL);
00377 #if CMI_SWAPGLOBALS
00378 doSwapglobals = (CtgCurrentGlobals() != NULL);
00379 #endif
00380 if (CmiThreadIs(CMI_THREAD_IS_TLS)) {
00381 CtgInstallMainThreadTLS(&oldtlsseg);
00382 }
00383
00384 TCharm::deactivateThread();
00385
00386 #if CMK_TRACE_ENABLED
00387 TCHARM_Api_trace(routineName,libraryName);
00388 #endif
00389 }
00390
00391
00392 ~TCharmAPIRoutine() noexcept {
00393 #if CMK_TRACE_ENABLED
00394 double stop = CmiWallTimer();
00395 #endif
00396
00397 TCharm *tc=CtvAccess(_curTCharm);
00398 if(tc != NULL){
00399
00400
00401 if(doIsomalloc){
00402 CmiIsomallocBlockListActivate(tc->heapBlocks);
00403 }
00404 #if CMI_SWAPGLOBALS
00405 if(doSwapglobals){
00406 CtgInstall(tc->threadGlobals);
00407 }
00408 #endif
00409 }
00410 if (CmiThreadIs(CMI_THREAD_IS_TLS)) {
00411 tlsseg_t cur;
00412 CtgInstallCthTLS(&cur, &oldtlsseg);
00413 }
00414
00415 #if CMK_BIGSIM_CHARM
00416 void *log;
00417 _TRACE_BG_TLINE_END(&log);
00418 _TRACE_BG_END_EXECUTE(0);
00419 _TRACE_BG_BEGIN_EXECUTE_NOMSG("user_code", &log, 0);
00420 if (CmiMyPe() == pe) _TRACE_BG_ADD_BACKWARD_DEP(callEvent);
00421 #endif
00422 #if CMK_TRACE_ENABLED
00423 if (tcharm_routineID > -1)
00424 traceUserBracketEventNestedID(tcharm_routineID, start, stop, TCHARM_Element());
00425 #endif
00426 }
00427 };
00428
00429
00430 #define TCHARMAPI(routineName) TCHARM_API_TRACE(routineName,"tcharm");
00431
00432
00433 FLINKAGE void FTN_NAME(TCHARM_USER_NODE_SETUP,tcharm_user_node_setup)(void);
00434 FLINKAGE void FTN_NAME(TCHARM_USER_SETUP,tcharm_user_setup)(void);
00435
00436
00437 #endif
00438
00439