[project @ 1999-11-02 15:05:38 by simonmar]
[ghc-hetmet.git] / ghc / rts / Schedule.h
1 /* -----------------------------------------------------------------------------
2  * $Id: Schedule.h,v 1.9 1999/11/02 15:06:02 simonmar Exp $
3  *
4  * (c) The GHC Team 1998-1999
5  *
6  * Prototypes for functions in Schedule.c 
7  * (RTS internal scheduler interface)
8  *
9  * ---------------------------------------------------------------------------*/
10
11 /* initScheduler(), exitScheduler(), startTasks()
12  * 
13  * Called from STG :  no
14  * Locks assumed   :  none
15  */
16 void initScheduler( void );
17 void exitScheduler( void );
18 #ifdef SMP
19 void startTasks( void );
20 #endif
21
22 /* awakenBlockedQueue()
23  *
24  * Takes a pointer to the beginning of a blocked TSO queue, and
25  * wakes up the entire queue.
26  *
27  * Called from STG :  yes
28  * Locks assumed   :  none
29  */
30 void awakenBlockedQueue(StgTSO *tso);
31
32 /* unblockOne()
33  *
34  * Takes a pointer to the beginning of a blocked TSO queue, and
35  * removes the first thread, placing it on the runnable queue.
36  *
37  * Called from STG : yes
38  * Locks assumed   : none
39  */
40 StgTSO *unblockOne(StgTSO *tso);
41
42 /* raiseAsync()
43  *
44  * Raises an exception asynchronously in the specified thread.
45  *
46  * Called from STG :  yes
47  * Locks assumed   :  none
48  */
49 void raiseAsync(StgTSO *tso, StgClosure *exception);
50
51 /* awaitEvent()
52  *
53  * Raises an exception asynchronously in the specified thread.
54  *
55  * Called from STG :  NO
56  * Locks assumed   :  sched_mutex
57  */
58 void awaitEvent(rtsBool wait);  /* In Select.c */
59
60 /* Context switch flag.
61  * Locks required  : sched_mutex
62  */
63 extern nat context_switch;
64
65 extern  nat ticks_since_select;
66
67 /* Capability type
68  */
69 typedef StgRegTable Capability;
70
71 /* Free capability list.
72  * Locks required: sched_mutex.
73  */
74 #ifdef SMP
75 extern Capability *free_capabilities;
76 extern nat n_free_capabilities;
77 #else
78 extern Capability MainRegTable;
79 #endif
80
81 /* Thread queues.
82  * Locks required  : sched_mutex
83  */
84 extern  StgTSO *run_queue_hd, *run_queue_tl;
85 extern  StgTSO *blocked_queue_hd, *blocked_queue_tl;
86
87 #ifdef DEBUG
88 extern void printThreadBlockage(StgTSO *tso);
89 #endif
90
91 #ifdef SMP
92 extern pthread_mutex_t sched_mutex;
93 extern pthread_cond_t  thread_ready_cond;
94 extern pthread_cond_t  gc_pending_cond;
95 #endif
96
97 #ifdef SMP
98 typedef struct {
99   pthread_t id;
100   double    mut_time;
101   double    gc_time;
102   double    gc_etime;
103 } task_info;
104
105 extern task_info *task_ids;
106 #endif
107
108 /* -----------------------------------------------------------------------------
109  * Some convenient macros...
110  */
111
112 #define END_TSO_QUEUE  ((StgTSO *)(void*)&END_TSO_QUEUE_closure)
113 #define END_CAF_LIST   ((StgCAF *)(void*)&END_TSO_QUEUE_closure)
114
115 /* Add a thread to the end of the run queue.
116  * NOTE: tso->link should be END_TSO_QUEUE before calling this macro.
117  */
118 #define APPEND_TO_RUN_QUEUE(tso)                \
119     ASSERT(tso->link == END_TSO_QUEUE);         \
120     if (run_queue_hd == END_TSO_QUEUE) {        \
121       run_queue_hd = tso;                       \
122     } else {                                    \
123       run_queue_tl->link = tso;                 \
124     }                                           \
125     run_queue_tl = tso;
126
127 /* Push a thread on the beginning of the run queue.  Used for
128  * newly awakened threads, so they get run as soon as possible.
129  */
130 #define PUSH_ON_RUN_QUEUE(tso)                  \
131     tso->link = run_queue_hd;                   \
132       run_queue_hd = tso;                       \
133     if (run_queue_tl == END_TSO_QUEUE) {        \
134       run_queue_tl = tso;                       \
135     }
136     
137 /* Pop the first thread off the runnable queue.
138  */
139 #define POP_RUN_QUEUE()                         \
140   ({ StgTSO *t = run_queue_hd;                  \
141     if (t != END_TSO_QUEUE) {                   \
142       run_queue_hd = t->link;                   \
143       t->link = END_TSO_QUEUE;                  \
144       if (run_queue_hd == END_TSO_QUEUE) {      \
145         run_queue_tl = END_TSO_QUEUE;           \
146       }                                         \
147     }                                           \
148     t;                                          \
149   })
150
151 /* Add a thread to the end of the blocked queue.
152  */
153 #define APPEND_TO_BLOCKED_QUEUE(tso)            \
154     ASSERT(tso->link == END_TSO_QUEUE);         \
155     if (blocked_queue_hd == END_TSO_QUEUE) {    \
156       blocked_queue_hd = tso;                   \
157     } else {                                    \
158       blocked_queue_tl->link = tso;             \
159     }                                           \
160     blocked_queue_tl = tso;
161
162 /* Signal that a runnable thread has become available, in
163  * case there are any waiting tasks to execute it.
164  */
165 #ifdef SMP
166 #define THREAD_RUNNABLE()                       \
167   if (free_capabilities != NULL) {              \
168      pthread_cond_signal(&thread_ready_cond);   \
169   }                                             \
170   context_switch = 1;
171 #else
172 #define THREAD_RUNNABLE()  /* nothing */
173 #endif
174