Add TCharm::ckCheckpoint, TCharm::ckRestart, and helper function TCharm::clear
[charm.git] / src / libs / ck-libs / tcharm / tcharm_impl.h
1 /*
2 Threaded Charm++ "Framework Framework" Implementation header
3
4 Implements an array of migratable threads.
5 Provides utility routines for registering user
6 data, stopping, starting, and migrating threads.
7
8 Orion Sky Lawlor, olawlor@acm.org, 11/19/2001
9 */
10 #ifndef __CHARM_TCHARM_IMPL_H
11 #define __CHARM_TCHARM_IMPL_H
12
13 #include "pup.h"
14 #include "pup_c.h"
15 #include "charm-api.h"
16 #include "tcharmc.h"
17 #include "cklists.h"
18 #include "memory-isomalloc.h"
19
20 //User's readonly global variables, set exactly once after initialization
21 class TCharmReadonlys {
22         //There's only one (shared) list per node, so no CpvAccess here
23         static CkVec<TCpupReadonlyGlobal> entries;
24  public:
25         static void add(TCpupReadonlyGlobal fn);
26         //Pups all registered readonlys 
27         static void pupAllReadonlys(PUP::er &p);
28
29         //Used by parameter marshalling:
30         void pup(PUP::er &p);
31 };
32 PUPmarshall(TCharmReadonlys);
33
34 class TCharmTraceLibList;
35
36 #include "tcharm.decl.h"
37
38 class TCharmReadonlyGroup : public Group {
39  public:
40         //Just unpacking the parameter is enough:
41         TCharmReadonlyGroup(const TCharmReadonlys &r) { /*nothing needed*/ }
42 };
43
44 class TCharm;
45
46 class TCharmInitMsg : public CMessage_TCharmInitMsg {
47  public:
48         //Function to start thread with:
49         CthVoidFn threadFn;
50         //Initial stack size, in bytes:
51         int stackSize;
52         //Array size (number of elements)
53         int numElements;
54         //Data to pass to thread:
55         char *data;
56
57         TCharmInitMsg(CthVoidFn threadFn_,int stackSize_)
58                 :threadFn(threadFn_), stackSize(stackSize_) {}
59 };
60
61 //Current computation location
62 typedef enum {inNodeSetup,inInit,inDriver,inFramework,inPup} inState;
63
64 //Thread-local variables:
65 CtvExtern(TCharm *,_curTCharm);
66 CpvExtern(inState,_stateTCharm);
67
68 CDECL {typedef void (*TCpupUserDataC)(pup_er p,void *data);};
69 FDECL {typedef void (*TCpupUserDataF)(pup_er p,void *data);};
70
71 class TCharm: public ArrayElement1D
72 {
73  public:
74
75         //User's heap-allocated/global data:
76         class UserData {
77                 void *data; //user data pointer
78                 bool isC;
79                 TCpupUserDataC cfn;
80                 TCpupUserDataF ffn;
81         public:
82                 UserData(int i=0) {data=NULL; cfn=NULL; ffn=NULL;}
83                 UserData(TCpupUserDataC cfn_,void *data_)
84                         {cfn=cfn_; data=data_; isC=true;}
85                 class isFortran{};
86                 UserData(TCpupUserDataF ffn_,void *data_,isFortran tag)
87                         {ffn=ffn_; data=data_; isC=false;}
88                 inline void *getData(void) const {return data;}
89                 void pup(PUP::er &p);
90                 friend inline void operator|(PUP::er &p,UserData &d) {d.pup(p);}
91         };
92         //New interface for user data:
93         CkVec<UserData> sud;
94
95         //One-time initialization
96         static void nodeInit(void);
97  private:
98         //Informational data about the current thread:
99         class ThreadInfo {
100         public:
101                 CProxy_TCharm tProxy; //Our proxy
102                 int thisElement; //Index of current element
103                 int numElements; //Number of array elements
104         };
105
106         TCharmInitMsg *initMsg; //Thread initialization data
107         CthThread tid; //Our migratable thread
108         friend class TCharmAPIRoutine; //So he can get to heapBlocks:
109         CmiIsomallocBlockList *heapBlocks; //Migratable heap data
110
111         bool isStopped;
112         ThreadInfo threadInfo;
113         double timeOffset; //Value to add to CkWallTimer to get my clock
114
115         //Old interface for user data:
116         enum {maxUserData=16};
117         int nUd;
118         UserData ud[maxUserData];
119
120         void ResumeFromSync(void);
121
122 #ifdef CMK_OPTIMIZE
123         static inline void check(void) {}
124 #else
125         static void check(void);
126 #endif
127
128  public:
129         TCharm(TCharmInitMsg *initMsg);
130         TCharm(CkMigrateMessage *);
131         ~TCharm();
132
133         void clear();
134         void ckCheckpoint(char* fname);
135         void ckRestart(char* fname);
136
137         //Pup routine packs the user data and migrates the thread
138         virtual void pup(PUP::er &p);
139
140         //Start running the thread for the first time
141         void run(void);
142
143         inline double getTimeOffset(void) const { return timeOffset; }
144
145 //Client-callable routines:
146         //One client is ready to run
147         void ready(void);
148
149         //Sleep till entire array is here
150         void barrier(void);
151
152         //Thread finished running
153         void done(void);
154
155         //Register user data to be packed with the thread
156         int add(const UserData &d);
157         void *lookupUserData(int ud);
158         
159         inline static TCharm *get(void) {check(); return CtvAccess(_curTCharm);}
160         inline static inState getState(void) {return CpvAccess(_stateTCharm);}
161         inline static void setState(inState to) {CpvAccess(_stateTCharm)=to;}
162         inline CthThread getThread(void) {return tid;}
163         inline const CProxy_TCharm &getProxy(void) const {return threadInfo.tProxy;}
164         inline int getElement(void) const {return threadInfo.thisElement;}
165         inline int getNumElements(void) const {return threadInfo.numElements;}
166
167         //Start/stop load balancer measurements
168         inline void stopTiming(void) {ckStopTiming();}
169         inline void startTiming(void) {ckStartTiming();}
170
171         //Block our thread, run the scheduler, and come back
172         inline void schedule(void) {
173                 stopTiming();
174                 CthYield();
175                 startTiming();
176         }
177
178         //As above, but start/stop the thread itself, too.
179         void stop(void); //Blocks; will not return until "start" called.
180         void start(void);
181         //Aliases:
182         inline void suspend(void) {stop();}
183         inline void resume(void) {start();}
184
185         //Go to sync, block, possibly migrate, and then resume
186         void migrate(void);
187
188         //Make subsequent malloc's go into our list:
189         inline void activateHeap(void) {
190                 CmiIsomallocBlockListActivate(heapBlocks);
191         }
192         //Disable migratable memory
193         inline void deactivateHeap(void) {
194                 CmiIsomallocBlockListActivate(NULL);
195         }
196 };
197
198
199
200 //TCharm internal class: Controls array startup, ready, run and shutdown
201 class TCharmCoordinator {
202         static int nArrays; //Total number of running thread arrays
203         static TCharmCoordinator *head; //List of coordinators
204
205         TCharmCoordinator *next; //Next coordinator in list
206         CProxy_TCharm threads;//The threads I coordinate
207         int nThreads;//Number of threads (array elements)
208         int nClients; //Number of bound client arrays
209         int nReady; //Number of ready clients
210 public:
211         TCharmCoordinator(CkArrayID threads,int nThreads);
212         ~TCharmCoordinator();
213         void addClient(const CkArrayID &client);
214         void clientReady(void);
215         void clientBarrier(void);
216         void clientDone(void);
217         
218         static int getTotal(void) {
219                 return nArrays;
220         }
221 };
222
223 //Controls initial setup (main::main & init routines)
224 class TCharmSetupCookie {
225         enum {correctMagic=0x5432abcd};
226         int magic; //To make sure this is actually a cookie
227         
228         int stackSize; //Thread stack size, in bytes
229         char **argv; //Command-line arguments
230         
231         CkArrayID tc; //Handle to last-created TCharm array
232         int numElements; //Number of elements in last-created TCharm
233         TCharmCoordinator *coord; 
234
235         //Points to the active cookie
236         static TCharmSetupCookie *theCookie;
237         friend class TCharmMain;
238  public:
239         TCharmSetupCookie(char **argv_);
240         
241 #ifdef CMK_OPTIMIZE //Skip check, for speed
242         inline TCharmSetupCookie &check(void) {return *this;}
243 #else
244         TCharmSetupCookie &check(void);
245 #endif
246         void setStackSize(int sz) {stackSize=sz;}
247         int getStackSize(void) const {return stackSize;}
248         char **getArgv(void) {return argv;}
249         
250         bool hasThreads(void) const {return 0!=coord;}
251         const CkArrayID &getThreads(void) const {return tc;}
252         TCharmCoordinator *getCoordinator(void) {return coord;}
253         int getNumElements(void) const {return numElements;}
254
255         void addClient(const CkArrayID &client) {coord->addClient(client);}
256         
257         void setThreads(const CkArrayID &aid,int nel);
258
259         static TCharmSetupCookie *get(void) {return theCookie;}
260 };
261
262 //Created in all API routines: disables/enables migratable malloc
263 class TCharmAPIRoutine {
264  public:
265         TCharmAPIRoutine() { //Entering Charm++ from user code
266                 //Disable migratable memory allocation while in Charm++:
267                 CmiIsomallocBlockListActivate(NULL);
268         }
269         ~TCharmAPIRoutine() { //Returning to user code from Charm++:
270                 //Reenable migratable memory allocation
271                 TCharm *tc=CtvAccess(_curTCharm);
272                 if (tc!=NULL) tc->activateHeap();
273         }
274 };
275
276
277 #define TCHARMAPI(routineName) TCHARM_API_TRACE(routineName,"tcharm");
278
279 //Node setup callbacks: called at startup on each node
280 FDECL void FTN_NAME(TCHARM_USER_NODE_SETUP,tcharm_user_node_setup)(void);
281 FDECL void FTN_NAME(TCHARM_USER_SETUP,tcharm_user_setup)(void);
282
283
284 #endif
285
286