Added an easy-to-use barrier call, which internally uses a
[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         //Sleep till entire array is here
130         void barrier(void);
131
132         //Thread finished running
133         void done(void);
134
135         //Register user data to be packed with the thread
136         int add(const UserData &d);
137         void *lookupUserData(int ud);
138         
139         inline static TCharm *get(void) {check(); return CtvAccess(_curTCharm);}
140         inline static inState getState(void) {return CpvAccess(_stateTCharm);}
141         inline static void setState(inState to) {CpvAccess(_stateTCharm)=to;}
142         inline CthThread getThread(void) {return tid;}
143         inline const CProxy_TCharm &getProxy(void) const {return threadInfo.tProxy;}
144         inline int getElement(void) const {return threadInfo.thisElement;}
145         inline int getNumElements(void) const {return threadInfo.numElements;}
146
147         //Start/stop load balancer measurements
148         inline void stopTiming(void) {ckStopTiming();}
149         inline void startTiming(void) {ckStartTiming();}
150
151         //Block our thread, run the scheduler, and come back
152         inline void schedule(void) {
153                 stopTiming();
154                 CthYield();
155                 startTiming();
156         }
157
158         //As above, but start/stop the thread itself, too.
159         void stop(void); //Blocks; will not return until "start" called.
160         void start(void);
161         //Aliases:
162         inline void suspend(void) {stop();}
163         inline void resume(void) {start();}
164
165         //Go to sync, block, possibly migrate, and then resume
166         void migrate(void);
167 };
168
169 //Controls array startup, ready, run and shutdown
170 class TCharmCoordinator {
171         static int nArrays; //Total number of running thread arrays
172         static TCharmCoordinator *head; //List of coordinators
173
174         TCharmCoordinator *next; //Next coordinator in list
175         CProxy_TCharm threads;//The threads I coordinate
176         int nThreads;//Number of threads (array elements)
177         int nClients; //Number of bound client arrays
178         int nReady; //Number of ready clients
179 public:
180         TCharmCoordinator(CkArrayID threads,int nThreads);
181         ~TCharmCoordinator();
182         void addClient(const CkArrayID &client);
183         void clientReady(void);
184         void clientBarrier(void);
185         void clientDone(void);
186         
187         static int getTotal(void) {
188                 return nArrays;
189         }
190 };
191
192 //Controls initial setup (main::main & init routines)
193 class TCharmSetupCookie {
194         enum {correctMagic=0x5432abcd};
195         int magic; //To make sure this is actually a cookie
196         
197         int stackSize; //Thread stack size, in bytes
198         char **argv; //Command-line arguments
199         
200         CkArrayID tc; //Handle to last-created TCharm array
201         int numElements; //Number of elements in last-created TCharm
202         TCharmCoordinator *coord; 
203
204         //Points to the active cookie
205         static TCharmSetupCookie *theCookie;
206         friend class TCharmMain;
207  public:
208         TCharmSetupCookie(char **argv_);
209         
210 #ifdef CMK_OPTIMIZE //Skip check, for speed
211         inline TCharmSetupCookie &check(void) {return *this;}
212 #else
213         TCharmSetupCookie &check(void);
214 #endif
215         void setStackSize(int sz) {stackSize=sz;}
216         int getStackSize(void) const {return stackSize;}
217         char **getArgv(void) {return argv;}
218         
219         bool hasThreads(void) const {return 0!=coord;}
220         const CkArrayID &getThreads(void) const {return tc;}
221         TCharmCoordinator *getCoordinator(void) {return coord;}
222         int getNumElements(void) const {return numElements;}
223
224         void addClient(const CkArrayID &client) {coord->addClient(client);}
225         
226         void setThreads(const CkArrayID &aid,int nel);
227
228         static TCharmSetupCookie *get(void) {return theCookie;}
229 };
230
231 //Node setup callbacks: called at startup on each node
232 FDECL void FTN_NAME(TCHARM_USER_NODE_SETUP,tcharm_user_node_setup)(void);
233 FDECL void FTN_NAME(TCHARM_USER_SETUP,tcharm_user_setup)(void);
234
235 //Library fallback setup routine:
236 typedef void (*TCharmFallbackSetupFn)(void);
237 void TCharmSetFallbackSetup(TCharmFallbackSetupFn f);
238
239 #endif
240
241