remove empty dir
[ghc-hetmet.git] / ghc / rts / Schedule.h
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team 1998-2005
4  *
5  * Prototypes for functions in Schedule.c 
6  * (RTS internal scheduler interface)
7  *
8  * -------------------------------------------------------------------------*/
9
10 #ifndef SCHEDULE_H
11 #define SCHEDULE_H
12
13 #include "OSThreads.h"
14 #include "Capability.h"
15
16 /* initScheduler(), exitScheduler()
17  * Called from STG :  no
18  * Locks assumed   :  none
19  */
20 void initScheduler (void);
21 void exitScheduler (void);
22
23 // Place a new thread on the run queue of the current Capability
24 void scheduleThread (Capability *cap, StgTSO *tso);
25
26 // Place a new thread on the run queue of a specified Capability
27 // (cap is the currently owned Capability, cpu is the number of
28 // the desired Capability).
29 void scheduleThreadOn(Capability *cap, StgWord cpu, StgTSO *tso);
30
31 /* awakenBlockedQueue()
32  *
33  * Takes a pointer to the beginning of a blocked TSO queue, and
34  * wakes up the entire queue.
35  * Called from STG :  yes
36  * Locks assumed   :  none
37  */
38 #if defined(GRAN)
39 void awakenBlockedQueue(StgBlockingQueueElement *q, StgClosure *node);
40 #elif defined(PAR)
41 void awakenBlockedQueue(StgBlockingQueueElement *q, StgClosure *node);
42 #else
43 void awakenBlockedQueue (Capability *cap, StgTSO *tso);
44 #endif
45
46 /* unblockOne()
47  *
48  * Put the specified thread on the run queue of the given Capability.
49  * Called from STG :  yes
50  * Locks assumed   :  we own the Capability.
51  */
52 StgTSO * unblockOne(Capability *cap, StgTSO *tso);
53
54 /* raiseAsync()
55  *
56  * Raises an exception asynchronously in the specified thread.
57  *
58  * Called from STG :  yes
59  * Locks assumed   :  none
60  */
61 void raiseAsync(Capability *cap, StgTSO *tso, StgClosure *exception);
62
63 /* suspendComputation()
64  *
65  * A variant of raiseAsync(), this strips the stack of the specified
66  * thread down to the stop_here point, leaving a current closure on
67  * top of the stack at [stop_here - 1].
68  */
69 void suspendComputation(Capability *cap, StgTSO *tso, StgPtr stop_here);
70
71 /* raiseExceptionHelper */
72 StgWord raiseExceptionHelper (StgRegTable *reg, StgTSO *tso, StgClosure *exception);
73
74 /* findRetryFrameHelper */
75 StgWord findRetryFrameHelper (StgTSO *tso);
76
77 /* GetRoots(evac_fn f)
78  *
79  * Call f() for each root known to the scheduler.
80  *
81  * Called from STG :  NO
82  * Locks assumed   :  ????
83  */
84 void GetRoots(evac_fn);
85
86 /* workerStart()
87  * 
88  * Entry point for a new worker task.
89  * Called from STG :  NO
90  * Locks assumed   :  none
91  */
92 void workerStart(Task *task);
93
94 #if defined(GRAN)
95 void    awaken_blocked_queue(StgBlockingQueueElement *q, StgClosure *node);
96 void    unlink_from_bq(StgTSO* tso, StgClosure* node);
97 void    initThread(StgTSO *tso, nat stack_size, StgInt pri);
98 #elif defined(PAR)
99 nat     run_queue_len(void);
100 void    awaken_blocked_queue(StgBlockingQueueElement *q, StgClosure *node);
101 void    initThread(StgTSO *tso, nat stack_size);
102 #else
103 char   *info_type(StgClosure *closure);    // dummy
104 char   *info_type_by_ip(StgInfoTable *ip); // dummy
105 void    awaken_blocked_queue(StgTSO *q);
106 void    initThread(StgTSO *tso, nat stack_size);
107 #endif
108
109 /* Context switch flag.
110  * Locks required  : none (conflicts are harmless)
111  */
112 extern int RTS_VAR(context_switch);
113
114 /* The state of the scheduler.  This is used to control the sequence
115  * of events during shutdown, and when the runtime is interrupted
116  * using ^C.
117  */
118 #define SCHED_RUNNING       0  /* running as normal */
119 #define SCHED_INTERRUPTING  1  /* ^C detected, before threads are deleted */
120 #define SCHED_INTERRUPTED   2  /* ^C detected, after threads deleted */
121 #define SCHED_SHUTTING_DOWN 3  /* final shutdown */
122
123 extern rtsBool RTS_VAR(sched_state);
124
125 /* 
126  * flag that tracks whether we have done any execution in this time slice.
127  */
128 #define ACTIVITY_YES      0 /* there has been activity in the current slice */
129 #define ACTIVITY_MAYBE_NO 1 /* no activity in the current slice */
130 #define ACTIVITY_INACTIVE 2 /* a complete slice has passed with no activity */
131 #define ACTIVITY_DONE_GC  3 /* like 2, but we've done a GC too */
132
133 /* Recent activity flag.
134  * Locks required  : Transition from MAYBE_NO to INACTIVE
135  * happens in the timer signal, so it is atomic.  Trnasition from
136  * INACTIVE to DONE_GC happens under sched_mutex.  No lock required
137  * to set it to ACTIVITY_YES.
138  */
139 extern nat recent_activity;
140
141 /* Thread queues.
142  * Locks required  : sched_mutex
143  *
144  * In GranSim we have one run/blocked_queue per PE.
145  */
146 #if defined(GRAN)
147 // run_queue_hds defined in GranSim.h
148 #else
149 extern  StgTSO *RTS_VAR(blackhole_queue);
150 #if !defined(THREADED_RTS)
151 extern  StgTSO *RTS_VAR(blocked_queue_hd), *RTS_VAR(blocked_queue_tl);
152 extern  StgTSO *RTS_VAR(sleeping_queue);
153 #endif
154 #endif
155
156 /* Linked list of all threads.
157  * Locks required  : sched_mutex
158  */
159 extern  StgTSO *RTS_VAR(all_threads);
160
161 /* Set to rtsTrue if there are threads on the blackhole_queue, and
162  * it is possible that one or more of them may be available to run.
163  * This flag is set to rtsFalse after we've checked the queue, and
164  * set to rtsTrue just before we run some Haskell code.  It is used
165  * to decide whether we should yield the Capability or not.
166  * Locks required  : none (see scheduleCheckBlackHoles()).
167  */
168 extern rtsBool blackholes_need_checking;
169
170 #if defined(THREADED_RTS)
171 extern Mutex RTS_VAR(sched_mutex);
172 #endif
173
174 StgBool isThreadBound(StgTSO *tso);
175
176 SchedulerStatus rts_mainLazyIO(HaskellObj p, /*out*/HaskellObj *ret);
177
178 /* Called by shutdown_handler(). */
179 void interruptStgRts (void);
180
181 nat  run_queue_len (void);
182
183 void resurrectThreads (StgTSO *);
184
185 void printAllThreads(void);
186
187 /* debugging only 
188  */
189 #ifdef DEBUG
190 void print_bq (StgClosure *node);
191 #endif
192 #if defined(PAR)
193 void print_bqe (StgBlockingQueueElement *bqe);
194 #endif
195
196 void labelThread(StgPtr tso, char *label);
197
198 /* -----------------------------------------------------------------------------
199  * Some convenient macros/inline functions...
200  */
201
202 #if !IN_STG_CODE
203
204 /* END_TSO_QUEUE and friends now defined in includes/StgMiscClosures.h */
205
206 /* Add a thread to the end of the run queue.
207  * NOTE: tso->link should be END_TSO_QUEUE before calling this macro.
208  * ASSUMES: cap->running_task is the current task.
209  */
210 STATIC_INLINE void
211 appendToRunQueue (Capability *cap, StgTSO *tso)
212 {
213     ASSERT(tso->link == END_TSO_QUEUE);
214     if (cap->run_queue_hd == END_TSO_QUEUE) {
215         cap->run_queue_hd = tso;
216     } else {
217         cap->run_queue_tl->link = tso;
218     }
219     cap->run_queue_tl = tso;
220 }
221
222 /* Push a thread on the beginning of the run queue.  Used for
223  * newly awakened threads, so they get run as soon as possible.
224  * ASSUMES: cap->running_task is the current task.
225  */
226 STATIC_INLINE void
227 pushOnRunQueue (Capability *cap, StgTSO *tso)
228 {
229     tso->link = cap->run_queue_hd;
230     cap->run_queue_hd = tso;
231     if (cap->run_queue_tl == END_TSO_QUEUE) {
232         cap->run_queue_tl = tso;
233     }
234 }
235
236 /* Pop the first thread off the runnable queue.
237  */
238 STATIC_INLINE StgTSO *
239 popRunQueue (Capability *cap)
240
241     StgTSO *t = cap->run_queue_hd;
242     ASSERT(t != END_TSO_QUEUE);
243     cap->run_queue_hd = t->link;
244     t->link = END_TSO_QUEUE;
245     if (cap->run_queue_hd == END_TSO_QUEUE) {
246         cap->run_queue_tl = END_TSO_QUEUE;
247     }
248     return t;
249 }
250
251 /* Add a thread to the end of the blocked queue.
252  */
253 #if !defined(THREADED_RTS)
254 STATIC_INLINE void
255 appendToBlockedQueue(StgTSO *tso)
256 {
257     ASSERT(tso->link == END_TSO_QUEUE);
258     if (blocked_queue_hd == END_TSO_QUEUE) {
259         blocked_queue_hd = tso;
260     } else {
261         blocked_queue_tl->link = tso;
262     }
263     blocked_queue_tl = tso;
264 }
265 #endif
266
267 #if defined(THREADED_RTS)
268 STATIC_INLINE void
269 appendToWakeupQueue (Capability *cap, StgTSO *tso)
270 {
271     ASSERT(tso->link == END_TSO_QUEUE);
272     if (cap->wakeup_queue_hd == END_TSO_QUEUE) {
273         cap->wakeup_queue_hd = tso;
274     } else {
275         cap->wakeup_queue_tl->link = tso;
276     }
277     cap->wakeup_queue_tl = tso;
278 }
279 #endif
280
281 /* Check whether various thread queues are empty
282  */
283 STATIC_INLINE rtsBool
284 emptyQueue (StgTSO *q)
285 {
286     return (q == END_TSO_QUEUE);
287 }
288
289 STATIC_INLINE rtsBool
290 emptyRunQueue(Capability *cap)
291 {
292     return emptyQueue(cap->run_queue_hd);
293 }
294
295 #if defined(THREADED_RTS)
296 STATIC_INLINE rtsBool
297 emptyWakeupQueue(Capability *cap)
298 {
299     return emptyQueue(cap->wakeup_queue_hd);
300 }
301 #endif
302
303 #if !defined(THREADED_RTS)
304 #define EMPTY_BLOCKED_QUEUE()  (emptyQueue(blocked_queue_hd))
305 #define EMPTY_SLEEPING_QUEUE() (emptyQueue(sleeping_queue))
306 #endif
307
308 STATIC_INLINE rtsBool
309 emptyThreadQueues(Capability *cap)
310 {
311     return emptyRunQueue(cap)
312 #if !defined(THREADED_RTS)
313         && EMPTY_BLOCKED_QUEUE() && EMPTY_SLEEPING_QUEUE()
314 #endif
315     ;
316 }
317
318 #ifdef DEBUG
319 void sched_belch(char *s, ...)
320    GNU_ATTRIBUTE(format (printf, 1, 2));
321 #endif
322
323 #endif /* !IN_STG_CODE */
324
325 STATIC_INLINE void
326 dirtyTSO (StgTSO *tso)
327 {
328     tso->flags |= TSO_DIRTY;
329 }
330
331 #endif /* SCHEDULE_H */
332