Use message-passing to implement throwTo in the RTS
[ghc-hetmet.git] / includes / rts / storage / TSO.h
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2009
4  *
5  * The definitions for Thread State Objects.
6  *
7  * ---------------------------------------------------------------------------*/
8
9 #ifndef RTS_STORAGE_TSO_H
10 #define RTS_STORAGE_TSO_H
11
12 /*
13  * PROFILING info in a TSO
14  */
15 typedef struct {
16   CostCentreStack *CCCS;        /* thread's current CCS */
17 } StgTSOProfInfo;
18
19 /*
20  * There is no TICKY info in a TSO at this time.
21  */
22
23 /*
24  * Thread IDs are 32 bits.
25  */
26 typedef StgWord32 StgThreadID;
27
28 #define tsoLocked(tso) ((tso)->flags & TSO_LOCKED)
29
30 /*
31  * Type returned after running a thread.  Values of this type
32  * include HeapOverflow, StackOverflow etc.  See Constants.h for the
33  * full list.
34  */
35 typedef unsigned int StgThreadReturnCode;
36
37 #if defined(mingw32_HOST_OS)
38 /* results from an async I/O request + its request ID. */
39 typedef struct {
40   unsigned int reqID;
41   int          len;
42   int          errCode;
43 } StgAsyncIOResult;
44 #endif
45
46 /* Reason for thread being blocked. See comment above struct StgTso_. */
47 typedef union {
48   StgClosure *closure;
49   struct MessageThrowTo_ *throwto;
50   struct MessageWakeup_  *wakeup;
51   StgInt fd;    /* StgInt instead of int, so that it's the same size as the ptrs */
52 #if defined(mingw32_HOST_OS)
53   StgAsyncIOResult *async_result;
54 #endif
55   StgWord target;
56 } StgTSOBlockInfo;
57
58
59 /*
60  * TSOs live on the heap, and therefore look just like heap objects.
61  * Large TSOs will live in their own "block group" allocated by the
62  * storage manager, and won't be copied during garbage collection.
63  */
64
65 /*
66  * Threads may be blocked for several reasons.  A blocked thread will
67  * have the reason in the why_blocked field of the TSO, and some
68  * further info (such as the closure the thread is blocked on, or the
69  * file descriptor if the thread is waiting on I/O) in the block_info
70  * field.
71  */
72
73 typedef struct StgTSO_ {
74     StgHeader               header;
75
76     /* The link field, for linking threads together in lists (e.g. the
77        run queue on a Capability.
78     */
79     struct StgTSO_*         _link;
80     /*
81        NOTE!!!  do not modify _link directly, it is subject to
82        a write barrier for generational GC.  Instead use the
83        setTSOLink() function.  Exceptions to this rule are:
84
85        * setting the link field to END_TSO_QUEUE
86        * putting a TSO on the blackhole_queue
87        * setting the link field of the currently running TSO, as it
88          will already be dirty.
89     */
90
91     struct StgTSO_*         global_link;    // Links threads on the
92                                             // generation->threads lists
93     
94     StgWord                 dirty;          /* non-zero => dirty */
95     /*
96      * The tso->dirty flag indicates that this TSO's stack should be
97      * scanned during garbage collection.  It also indicates that this
98      * TSO is on the mutable list.
99      *
100      * NB. The dirty flag gets a word to itself, so that it can be set
101      * safely by multiple threads simultaneously (the flags field is
102      * not safe for this purpose; see #3429).  It is harmless for the
103      * TSO to be on the mutable list multiple times.
104      *
105      * tso->dirty is set by dirty_TSO(), and unset by the garbage
106      * collector (only).
107      *
108      * The link field has a separate dirty bit of its own, namely the
109      * bit TSO_LINK_DIRTY in the tso->flags field, set by
110      * setTSOLink().
111      */
112
113     StgWord16               what_next;      // Values defined in Constants.h
114     StgWord16               why_blocked;    // Values defined in Constants.h
115     StgWord32               flags;          // Values defined in Constants.h
116     StgTSOBlockInfo         block_info;
117     StgThreadID             id;
118     int                     saved_errno;
119     struct InCall_*         bound;
120     struct Capability_*     cap;
121     struct StgTRecHeader_ * trec;       /* STM transaction record */
122
123     /*
124        A list of threads blocked on this TSO waiting to throw
125        exceptions.  In order to access this field, the TSO must be
126        locked using lockClosure/unlockClosure (see SMP.h).
127     */
128     struct MessageThrowTo_ * blocked_exceptions;
129
130 #ifdef TICKY_TICKY
131     /* TICKY-specific stuff would go here. */
132 #endif
133 #ifdef PROFILING
134     StgTSOProfInfo prof;
135 #endif
136 #ifdef mingw32_HOST_OS
137     StgWord32 saved_winerror;
138 #endif
139
140     /* The thread stack... */
141     StgWord32          stack_size;     /* stack size in *words* */
142     StgWord32          max_stack_size; /* maximum stack size in *words* */
143     StgPtr             sp;
144     
145     StgWord            stack[FLEXIBLE_ARRAY];
146 } *StgTSOPtr;
147
148 /* -----------------------------------------------------------------------------
149    functions
150    -------------------------------------------------------------------------- */
151
152 void dirty_TSO  (Capability *cap, StgTSO *tso);
153 void setTSOLink (Capability *cap, StgTSO *tso, StgTSO *target);
154
155 /* -----------------------------------------------------------------------------
156    Invariants:
157
158    An active thread has the following properties:
159
160       tso->stack < tso->sp < tso->stack+tso->stack_size
161       tso->stack_size <= tso->max_stack_size
162       
163       RESERVED_STACK_WORDS is large enough for any heap-check or
164       stack-check failure.
165
166       The size of the TSO struct plus the stack is either
167         (a) smaller than a block, or
168         (b) a multiple of BLOCK_SIZE
169
170         tso->why_blocked       tso->block_info      location
171         ----------------------------------------------------------------------
172         NotBlocked             END_TSO_QUEUE        runnable_queue, or running
173         
174         BlockedOnBlackHole     the BLACKHOLE        blackhole_queue
175         
176         BlockedOnMVar          the MVAR             the MVAR's queue
177
178         BlockedOnSTM           END_TSO_QUEUE        STM wait queue(s)
179         
180         BlockedOnMsgThrowTo    MessageThrowTo *     TSO->blocked_exception
181
182         BlockedOnRead          NULL                 blocked_queue
183         BlockedOnWrite         NULL                 blocked_queue
184         BlockedOnDelay         NULL                 blocked_queue
185         BlockedOnGA            closure TSO blocks on   BQ of that closure
186         BlockedOnGA_NoSend     closure TSO blocks on   BQ of that closure
187
188       tso->link == END_TSO_QUEUE, if the thread is currently running.
189
190    A zombie thread has the following properties:
191       
192       tso->what_next == ThreadComplete or ThreadKilled
193       tso->link     ==  (could be on some queue somewhere)
194       tso->sp       ==  tso->stack + tso->stack_size - 1 (i.e. top stack word)
195       tso->sp[0]    ==  return value of thread, if what_next == ThreadComplete,
196                         exception             , if what_next == ThreadKilled
197
198       (tso->sp is left pointing at the top word on the stack so that
199       the return value or exception will be retained by a GC).
200
201    The 2 cases BlockedOnGA and BlockedOnGA_NoSend are needed in a GUM
202    setup only. They mark a TSO that has entered a FETCH_ME or
203    FETCH_ME_BQ closure, respectively; only the first TSO hitting the
204    closure will send a Fetch message.
205    Currently we have no separate code for blocking on an RBH; we use the
206    BlockedOnBlackHole case for that.   -- HWL
207
208  ---------------------------------------------------------------------------- */
209
210 /* Workaround for a bug/quirk in gcc on certain architectures.
211  * symptom is that (&tso->stack - &tso->header) /=  sizeof(StgTSO)
212  * in other words, gcc pads the structure at the end.
213  */
214
215 extern StgTSO dummy_tso;
216
217 #define TSO_STRUCT_SIZE \
218    ((char *)&dummy_tso.stack - (char *)&dummy_tso.header)
219
220 #define TSO_STRUCT_SIZEW (TSO_STRUCT_SIZE / sizeof(W_))
221
222 /* this is the NIL ptr for a TSO queue (e.g. runnable queue) */
223 #define END_TSO_QUEUE  ((StgTSO *)(void*)&stg_END_TSO_QUEUE_closure)
224
225 #endif /* RTS_STORAGE_TSO_H */