Minor bug fix: instead of relying on the initialization
[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 class TCharmTraceLibList;
21
22 #include "tcharm.decl.h"
23
24 class TCharm;
25
26 // This little class holds values between a call to TCHARM_Set_* 
27 //   and the subsequent TCHARM_Create_*.  It should be moved
28 //   into a parameter to TCHARM_Create.
29 class TCHARM_Thread_options {
30 public:
31         int stackSize; /* size of thread execution stack, in bytes */
32         int exitWhenDone; /* flag: call CkExit when thread is finished. */
33         // Fill out the default thread options:
34         TCHARM_Thread_options(int doDefault);
35         TCHARM_Thread_options() {}
36
37         void sanityCheck(void);
38 };
39
40 class TCharmInitMsg : public CMessage_TCharmInitMsg {
41  public:
42         //Function to start thread with:
43         CthVoidFn threadFn;
44         //Initial thread parameters:
45         TCHARM_Thread_options opts;
46         //Array size (number of elements)
47         int numElements;
48         //Data to pass to thread:
49         char *data;
50
51         TCharmInitMsg(CthVoidFn threadFn_,const TCHARM_Thread_options &opts_)
52                 :threadFn(threadFn_), opts(opts_) {}
53 };
54
55 //Thread-local variables:
56 CtvExtern(TCharm *,_curTCharm);
57
58 CDECL {typedef void (*TCpupUserDataC)(pup_er p,void *data);};
59 FDECL {typedef void (*TCpupUserDataF)(pup_er p,void *data);};
60
61 class TCharm: public CBase_TCharm
62 {
63  public:
64
65 //User's heap-allocated/global data:
66         class UserData {
67                 void *data; //user data pointer
68                 bool isC;
69                 TCpupUserDataC cfn;
70                 TCpupUserDataF ffn;
71         public:
72                 UserData(int i=0) {data=NULL; cfn=NULL; ffn=NULL;}
73                 UserData(TCpupUserDataC cfn_,void *data_)
74                         {cfn=cfn_; data=data_; isC=true;}
75                 class isFortran{};
76                 UserData(TCpupUserDataF ffn_,void *data_,isFortran tag)
77                         {ffn=ffn_; data=data_; isC=false;}
78                 inline void *getData(void) const {return data;}
79                 void pup(PUP::er &p);
80                 friend inline void operator|(PUP::er &p,UserData &d) {d.pup(p);}
81         };
82         //New interface for user data:
83         CkVec<UserData> sud;
84         
85 //Tiny semaphore-like pointer producer/consumer
86         class TCharmSemaphore {
87         public:
88                 int id; //User-defined identifier
89                 void *data; //User-defined data
90                 CthThread thread; //Waiting thread, or 0 if none
91                 
92                 TCharmSemaphore() { id=-1; data=NULL; thread=NULL; }
93                 TCharmSemaphore(int id_) { id=id_; data=NULL; thread=NULL; }
94         };
95         /// Short, unordered list of waiting semaphores.
96         CkVec<TCharmSemaphore> sema;
97         TCharmSemaphore *findSema(int id);
98         TCharmSemaphore *getSema(int id);
99         void freeSema(TCharmSemaphore *);
100         
101         /// Store data at the semaphore "id".
102         ///  The put can come before or after the get.
103         void semaPut(int id,void *data);
104
105         /// Retreive data from the semaphore "id", returning NULL if not there.
106         void *semaPeek(int id);
107         
108         /// Retreive data from the semaphore "id".
109         ///  Blocks if the data is not immediately available.
110         void *semaGets(int id);
111         
112         /// Retreive data from the semaphore "id".
113         ///  Blocks if the data is not immediately available.
114         ///  Consumes the data, so another put will be required for the next get.
115         void *semaGet(int id);
116
117 //One-time initialization
118         static void nodeInit(void);
119         static void procInit(void);
120  private:
121         //Informational data about the current thread:
122         class ThreadInfo {
123         public:
124                 CProxy_TCharm tProxy; //Our proxy
125                 int thisElement; //Index of current element
126                 int numElements; //Number of array elements
127         };
128
129         TCharmInitMsg *initMsg; //Thread initialization data
130         CthThread tid; //Our migratable thread
131         friend class TCharmAPIRoutine; //So he can get to heapBlocks:
132         CmiIsomallocBlockList *heapBlocks; //Migratable heap data
133
134         bool isStopped, resumeAfterMigration, exitWhenDone;
135         ThreadInfo threadInfo;
136         double timeOffset; //Value to add to CkWallTimer to get my clock
137
138         //Old interface for user data:
139         enum {maxUserData=16};
140         int nUd;
141         UserData ud[maxUserData];
142
143         void ResumeFromSync(void);
144
145  public:
146         TCharm(TCharmInitMsg *initMsg);
147         TCharm(CkMigrateMessage *);
148         ~TCharm();
149         
150         virtual void ckJustMigrated(void);
151         void migrateDelayed(int destPE);
152         void atBarrier(CkReductionMsg *);
153         void atExit(CkReductionMsg *);
154
155         void clear();
156
157         //Pup routine packs the user data and migrates the thread
158         virtual void pup(PUP::er &p);
159
160         //Start running the thread for the first time
161         void run(void);
162
163         inline double getTimeOffset(void) const { return timeOffset; }
164
165 //Client-callable routines:
166         //Sleep till entire array is here
167         void barrier(void);
168         
169         //Block, migrate to destPE, and resume
170         void migrateTo(int destPE);
171
172         //Thread finished running
173         void done(void);
174
175         //Register user data to be packed with the thread
176         int add(const UserData &d);
177         void *lookupUserData(int ud);
178         
179         inline static TCharm *get(void) {
180                 TCharm *c=getNULL();
181 #ifndef CMK_OPTIMIZE
182                 if (!c) ::CkAbort("TCharm has not been initialized!\n");
183 #endif
184                 return c;
185         }
186         inline static TCharm *getNULL(void) {return CtvAccess(_curTCharm);}
187         inline CthThread getThread(void) {return tid;}
188         inline const CProxy_TCharm &getProxy(void) const {return threadInfo.tProxy;}
189         inline int getElement(void) const {return threadInfo.thisElement;}
190         inline int getNumElements(void) const {return threadInfo.numElements;}
191
192         //Start/stop load balancer measurements
193         inline void stopTiming(void) {ckStopTiming();}
194         inline void startTiming(void) {ckStartTiming();}
195
196         //Block our thread, run the scheduler, and come back
197         void schedule(void);
198
199         //As above, but start/stop the thread itself, too.
200         void stop(void); //Blocks; will not return until "start" called.
201         void start(void);
202         //Aliases:
203         inline void suspend(void) {stop();}
204         inline void resume(void) { if (isStopped) start();}
205
206         //Go to sync, block, possibly migrate, and then resume
207         void migrate(void);
208
209         //Make subsequent malloc's go into our list:
210         inline void activateHeap(void) {
211                 CmiIsomallocBlockListActivate(heapBlocks);
212         }
213         //Disable migratable memory
214         inline void deactivateHeap(void) {
215                 CmiIsomallocBlockListActivate(NULL);
216         }
217 };
218
219
220 //Created in all API routines: disables/enables migratable malloc
221 class TCharmAPIRoutine {
222  public:
223         TCharmAPIRoutine() { //Entering Charm++ from user code
224                 //Disable migratable memory allocation while in Charm++:
225                 CmiIsomallocBlockListActivate(NULL);
226         }
227         ~TCharmAPIRoutine() { //Returning to user code from Charm++:
228                 //Reenable migratable memory allocation
229                 TCharm *tc=CtvAccess(_curTCharm);
230                 if (tc!=NULL) tc->activateHeap();
231         }
232 };
233
234
235 #define TCHARMAPI(routineName) TCHARM_API_TRACE(routineName,"tcharm");
236
237 //Node setup callbacks: called at startup on each node
238 FDECL void FTN_NAME(TCHARM_USER_NODE_SETUP,tcharm_user_node_setup)(void);
239 FDECL void FTN_NAME(TCHARM_USER_SETUP,tcharm_user_setup)(void);
240
241
242 #endif
243
244