root/includes/rts/storage/TSO.h

Revision 9d26519c20194abc3832578a55fbe31327519eeb, 8.6 KB (checked in by Simon Marlow <marlowsd@…>, 7 weeks ago)

Improve the handling of threadDelay in the non-threaded RTS

Firstly, we were rounding up too much, such that the smallest delay
was 20ms. Secondly, there is no need to use millisecond resolution on
a 64-bit machine where we have room in the TSO to use the normal
nanosecond resolution that we use elsewhere in the RTS.

  • Property mode set to 100644
Line 
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 */
15typedef 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 */
26typedef 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 */
35typedef unsigned int StgThreadReturnCode;
36
37#if defined(mingw32_HOST_OS)
38/* results from an async I/O request + its request ID. */
39typedef 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_. */
47typedef union {
48  StgClosure *closure;
49  StgTSO *prev; // a back-link when the TSO is on the run queue (NotBlocked)
50  struct MessageBlackHole_ *bh;
51  struct MessageThrowTo_ *throwto;
52  struct MessageWakeup_  *wakeup;
53  StgInt fd;    /* StgInt instead of int, so that it's the same size as the ptrs */
54#if defined(mingw32_HOST_OS)
55  StgAsyncIOResult *async_result;
56#endif
57#if !defined(THREADED_RTS)
58  StgWord target;
59    // Only for the non-threaded RTS: the target time for a thread
60    // blocked in threadDelay, in units of 1ms.  This is a
61    // compromise: we don't want to take up much space in the TSO.  If
62    // you want better resolution for threadDelay, use -threaded.
63#endif
64} StgTSOBlockInfo;
65
66
67/*
68 * TSOs live on the heap, and therefore look just like heap objects.
69 * Large TSOs will live in their own "block group" allocated by the
70 * storage manager, and won't be copied during garbage collection.
71 */
72
73/*
74 * Threads may be blocked for several reasons.  A blocked thread will
75 * have the reason in the why_blocked field of the TSO, and some
76 * further info (such as the closure the thread is blocked on, or the
77 * file descriptor if the thread is waiting on I/O) in the block_info
78 * field.
79 */
80
81typedef struct StgTSO_ {
82    StgHeader               header;
83
84    /* The link field, for linking threads together in lists (e.g. the
85       run queue on a Capability.
86    */
87    struct StgTSO_*         _link;
88    /*
89      Currently used for linking TSOs on:
90      * cap->run_queue_{hd,tl}
91      * (non-THREADED_RTS); the blocked_queue
92      * and pointing to the next chunk for a ThreadOldStack
93
94       NOTE!!!  do not modify _link directly, it is subject to
95       a write barrier for generational GC.  Instead use the
96       setTSOLink() function.  Exceptions to this rule are:
97
98       * setting the link field to END_TSO_QUEUE
99       * setting the link field of the currently running TSO, as it
100         will already be dirty.
101    */
102
103    struct StgTSO_*         global_link;    // Links threads on the
104                                            // generation->threads lists
105   
106    /*
107     * The thread's stack
108     */
109    struct StgStack_       *stackobj;
110
111    /*
112     * The tso->dirty flag indicates that this TSO's stack should be
113     * scanned during garbage collection.  It also indicates that this
114     * TSO is on the mutable list.
115     *
116     * NB. The dirty flag gets a word to itself, so that it can be set
117     * safely by multiple threads simultaneously (the flags field is
118     * not safe for this purpose; see #3429).  It is harmless for the
119     * TSO to be on the mutable list multiple times.
120     *
121     * tso->dirty is set by dirty_TSO(), and unset by the garbage
122     * collector (only).
123     */
124
125    StgWord16               what_next;      // Values defined in Constants.h
126    StgWord16               why_blocked;    // Values defined in Constants.h
127    StgWord32               flags;          // Values defined in Constants.h
128    StgTSOBlockInfo         block_info;
129    StgThreadID             id;
130    StgWord32               saved_errno;
131    StgWord32               dirty;          /* non-zero => dirty */
132    struct InCall_*         bound;
133    struct Capability_*     cap;
134
135    struct StgTRecHeader_ * trec;       /* STM transaction record */
136
137    /*
138     * A list of threads blocked on this TSO waiting to throw exceptions.
139    */
140    struct MessageThrowTo_ * blocked_exceptions;
141
142    /*
143     * A list of StgBlockingQueue objects, representing threads
144     * blocked on thunks that are under evaluation by this thread.
145    */
146    struct StgBlockingQueue_ *bq;
147
148#ifdef TICKY_TICKY
149    /* TICKY-specific stuff would go here. */
150#endif
151#ifdef PROFILING
152    StgTSOProfInfo prof;
153#endif
154#ifdef mingw32_HOST_OS
155    StgWord32 saved_winerror;
156#endif
157
158    /*
159     * sum of the sizes of all stack chunks (in words), used to decide
160     * whether to throw the StackOverflow exception when the stack
161     * overflows, or whether to just chain on another stack chunk.
162     *
163     * Note that this overestimates the real stack size, because each
164     * chunk will have a gap at the end, of +RTS -kb<size> words.
165     * This means stack overflows are not entirely accurate, because
166     * the more gaps there are, the sooner the stack will run into the
167     * hard +RTS -K<size> limit.
168     */
169    StgWord32  tot_stack_size;
170
171} *StgTSOPtr;
172
173typedef struct StgStack_ {
174    StgHeader  header;
175    StgWord32  stack_size;     // stack size in *words*
176    StgWord32  dirty;          // non-zero => dirty
177    StgPtr     sp;             // current stack pointer
178    StgWord    stack[FLEXIBLE_ARRAY];
179} StgStack;
180
181// Calculate SpLim from a TSO (reads tso->stackobj, but no fields from
182// the stackobj itself).
183INLINE_HEADER StgPtr tso_SpLim (StgTSO* tso)
184{
185    return tso->stackobj->stack + RESERVED_STACK_WORDS;
186}
187
188/* -----------------------------------------------------------------------------
189   functions
190   -------------------------------------------------------------------------- */
191
192void dirty_TSO  (Capability *cap, StgTSO *tso);
193void setTSOLink (Capability *cap, StgTSO *tso, StgTSO *target);
194void setTSOPrev (Capability *cap, StgTSO *tso, StgTSO *target);
195
196void dirty_STACK (Capability *cap, StgStack *stack);
197
198/* -----------------------------------------------------------------------------
199   Invariants:
200
201   An active thread has the following properties:
202
203      tso->stack < tso->sp < tso->stack+tso->stack_size
204      tso->stack_size <= tso->max_stack_size
205     
206      RESERVED_STACK_WORDS is large enough for any heap-check or
207      stack-check failure.
208
209      The size of the TSO struct plus the stack is either
210        (a) smaller than a block, or
211        (b) a multiple of BLOCK_SIZE
212
213        tso->why_blocked       tso->block_info      location
214        ----------------------------------------------------------------------
215        NotBlocked             END_TSO_QUEUE        runnable_queue, or running
216       
217        BlockedOnBlackHole     the BLACKHOLE        blackhole_queue
218       
219        BlockedOnMVar          the MVAR             the MVAR's queue
220
221        BlockedOnSTM           END_TSO_QUEUE        STM wait queue(s)
222       
223        BlockedOnMsgThrowTo    MessageThrowTo *     TSO->blocked_exception
224
225        BlockedOnRead          NULL                 blocked_queue
226        BlockedOnWrite         NULL                 blocked_queue
227        BlockedOnDelay         NULL                 blocked_queue
228        BlockedOnGA            closure TSO blocks on   BQ of that closure
229        BlockedOnGA_NoSend     closure TSO blocks on   BQ of that closure
230
231      tso->link == END_TSO_QUEUE, if the thread is currently running.
232
233   A zombie thread has the following properties:
234     
235      tso->what_next == ThreadComplete or ThreadKilled
236      tso->link     ==  (could be on some queue somewhere)
237      tso->sp       ==  tso->stack + tso->stack_size - 1 (i.e. top stack word)
238      tso->sp[0]    ==  return value of thread, if what_next == ThreadComplete,
239                        exception             , if what_next == ThreadKilled
240
241      (tso->sp is left pointing at the top word on the stack so that
242      the return value or exception will be retained by a GC).
243
244   The 2 cases BlockedOnGA and BlockedOnGA_NoSend are needed in a GUM
245   setup only. They mark a TSO that has entered a FETCH_ME or
246   FETCH_ME_BQ closure, respectively; only the first TSO hitting the
247   closure will send a Fetch message.
248   Currently we have no separate code for blocking on an RBH; we use the
249   BlockedOnBlackHole case for that.   -- HWL
250
251 ---------------------------------------------------------------------------- */
252
253/* this is the NIL ptr for a TSO queue (e.g. runnable queue) */
254#define END_TSO_QUEUE  ((StgTSO *)(void*)&stg_END_TSO_QUEUE_closure)
255
256#endif /* RTS_STORAGE_TSO_H */
Note: See TracBrowser for help on using the browser.