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