973db0c2d28bd08bcbb29d058adbf7ff4b609ae8
[charm.git] / src / libs / ck-libs / tcharm / tcharm.h
1 /*
2 Threaded Charm++ "Framework Framework"
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_H
11 #define __CHARM_TCHARM_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
19 //User's readonly global variables, set exactly once after initialization
20 class TCharmReadonlys {
21         //There's only one (shared) list per node, so no CpvAccess here
22         static CkVec<TCpupReadonlyGlobal> entries;
23  public:
24         static void add(TCpupReadonlyGlobal fn);
25         //Pups all registered readonlys
26         void pup(PUP::er &p);
27 };
28 PUPmarshall(TCharmReadonlys);
29
30 #include "tcharm.decl.h"
31
32 class TCharmReadonlyGroup : public Group {
33  public:
34         //Just unpacking the parameter is enough:
35         TCharmReadonlyGroup(const TCharmReadonlys &r) { /*nothing needed*/ }
36 };
37
38 class TCharm;
39
40 class TCharmInitMsg : public CMessage_TCharmInitMsg {
41  public:
42         //Function to start thread with:
43         CthVoidFn threadFn;
44         //Initial stack size, in bytes:
45         int stackSize;
46         //Array size (number of elements)
47         int numElements;
48         //Data to pass to thread:
49         char *data;
50         
51         TCharmInitMsg(CthVoidFn threadFn_,int stackSize_)
52                 :threadFn(threadFn_), stackSize(stackSize_) {}
53 };
54
55 //Current computation location
56 typedef enum {inNodeSetup,inInit,inDriver,inFramework,inPup} inState;
57
58 //Thread-local variables:
59 CtvExtern(TCharm *,_curTCharm);
60 CpvExtern(inState,_stateTCharm);
61
62 CDECL {typedef void (*TCpupUserDataC)(pup_er p,void *data);};
63 FDECL {typedef void (*TCpupUserDataF)(pup_er p,void *data);};
64
65 class TCharm: public ArrayElement1D
66 {
67  public:
68         
69         //User's heap-allocated/global data:
70         class UserData {
71                 void *data; //user data pointer
72                 bool isC;
73                 TCpupUserDataC cfn;
74                 TCpupUserDataF ffn;
75         public:
76                 UserData() {data=NULL; cfn=NULL; ffn=NULL;}
77                 UserData(TCpupUserDataC cfn_,void *data_)
78                         {cfn=cfn_; data=data_; isC=true;}
79                 class isFortran{};
80                 UserData(TCpupUserDataF ffn_,void *data_,isFortran tag)
81                         {ffn=ffn_; data=data_; isC=false;}
82                 void *getData(void) {return data;}
83                 void pup(PUP::er &p);
84         };
85
86         //One-time initialization
87         static void nodeInit(void);
88  private:
89         //Informational data about the current thread:
90         class ThreadInfo {
91         public:
92                 CProxy_TCharm tProxy; //Our proxy
93                 int thisElement; //Index of current element
94                 int numElements; //Number of array elements
95         };
96         
97         TCharmInitMsg *initMsg; //Thread initialization data
98         CthThread tid; //Our migratable thread
99         bool isStopped;
100         ThreadInfo threadInfo;
101
102         enum {maxUserData=16};
103         int nUd;
104         UserData ud[maxUserData];
105
106         void ResumeFromSync(void);
107
108 #ifdef CMK_OPTIMIZE
109         static inline void check(void) {}
110 #else
111         static void check(void);
112 #endif
113
114  public:
115         TCharm(TCharmInitMsg *initMsg);
116         TCharm(CkMigrateMessage *);
117         ~TCharm();
118         
119         //Pup routine packs the user data and migrates the thread
120         virtual void pup(PUP::er &p);
121
122         //Start running the thread for the first time
123         void run(void);
124
125 //Client-callable routines:
126         //One client is ready to run
127         void ready(void);
128
129         //Thread finished running
130         void done(void);
131
132         //Register user data to be packed with the thread
133         int add(const UserData &d);
134         void *lookupUserData(int ud);
135         
136         inline static TCharm *get(void) {check(); return CtvAccess(_curTCharm);}
137         inline static inState getState(void) {return CpvAccess(_stateTCharm);}
138         inline static void setState(inState to) {CpvAccess(_stateTCharm)=to;}
139         inline CthThread getThread(void) {return tid;}
140         inline const CProxy_TCharm &getProxy(void) const {return threadInfo.tProxy;}
141         inline int getElement(void) const {return threadInfo.thisElement;}
142         inline int getNumElements(void) const {return threadInfo.numElements;}
143
144         //Start/stop load balancer measurements
145         inline void stopTiming(void) {ckStopTiming();}
146         inline void startTiming(void) {ckStartTiming();}
147
148         //Block our thread, run the scheduler, and come back
149         inline void schedule(void) {
150                 stopTiming();
151                 CthYield();
152                 startTiming();
153         }
154
155         //As above, but start/stop the thread itself, too.
156         void stop(void); //Blocks; will not return until "start" called.
157         void start(void);
158         //Aliases:
159         inline void suspend(void) {stop();}
160         inline void resume(void) {start();}
161
162         //Go to sync, block, possibly migrate, and then resume
163         void migrate(void);
164 };
165
166 //Controls array startup, ready, run and shutdown
167 class TCharmCoordinator {
168         static int nArrays; //Total number of running thread arrays
169         static TCharmCoordinator *head; //List of coordinators
170
171         TCharmCoordinator *next; //Next coordinator in list
172         CProxy_TCharm threads;//The threads I coordinate
173         int nThreads;//Number of threads (array elements)
174         int nClients; //Number of bound client arrays
175         int nReady; //Number of ready clients
176 public:
177         TCharmCoordinator(CkArrayID threads,int nThreads);
178         ~TCharmCoordinator();
179         void addClient(const CkArrayID &client);
180         void clientReady(void);
181         void clientDone(void);
182         
183         static int getTotal(void) {
184                 return nArrays;
185         }
186 };
187
188 //Controls initial setup (main::main & init routines)
189 class TCharmSetupCookie {
190         enum {correctMagic=0x5432abcd};
191         int magic; //To make sure this is actually a cookie
192         
193         int stackSize; //Thread stack size, in bytes
194         char **argv; //Command-line arguments
195         
196         CkArrayID tc; //Handle to last-created TCharm array
197         int numElements; //Number of elements in last-created TCharm
198         TCharmCoordinator *coord; 
199
200         //Points to the active cookie
201         static TCharmSetupCookie *theCookie;
202         friend class TCharmMain;
203  public:
204         TCharmSetupCookie(char **argv_);
205         
206 #ifdef CMK_OPTIMIZE //Skip check, for speed
207         inline TCharmSetupCookie &check(void) {return *this;}
208 #else
209         TCharmSetupCookie &check(void);
210 #endif
211         void setStackSize(int sz) {stackSize=sz;}
212         int getStackSize(void) const {return stackSize;}
213         char **getArgv(void) {return argv;}
214         
215         bool hasThreads(void) const {return 0!=coord;}
216         const CkArrayID &getThreads(void) const {return tc;}
217         TCharmCoordinator *getCoordinator(void) {return coord;}
218         int getNumElements(void) const {return numElements;}
219
220         void addClient(const CkArrayID &client) {coord->addClient(client);}
221         
222         void setThreads(const CkArrayID &aid,int nel);
223
224         static TCharmSetupCookie *get(void) {return theCookie;}
225 };
226
227 //Node setup callbacks: called at startup on each node
228 FDECL void FTN_NAME(TCHARM_USER_NODE_SETUP,tcharm_user_node_setup)(void);
229 FDECL void FTN_NAME(TCHARM_USER_SETUP,tcharm_user_setup)(void);
230
231 //Library fallback setup routine:
232 typedef void (*TCharmFallbackSetupFn)(void);
233 void TCharmSetFallbackSetup(TCharmFallbackSetupFn f);
234
235 #endif
236
237