TSO.h 8.67 KB
Newer Older
1
/* -----------------------------------------------------------------------------
2
 *
Simon Marlow's avatar
Simon Marlow committed
3
 * (c) The GHC Team, 1998-2009
4
5
6
7
8
 *
 * The definitions for Thread State Objects.
 *
 * ---------------------------------------------------------------------------*/

Simon Marlow's avatar
Simon Marlow committed
9
10
#ifndef RTS_STORAGE_TSO_H
#define RTS_STORAGE_TSO_H
11

12
13
14
/*
 * PROFILING info in a TSO
 */
15
typedef struct {
16
  CostCentreStack *cccs;       /* thread's current CCS */
17
18
} StgTSOProfInfo;

19
/*
20
 * There is no TICKY info in a TSO at this time.
21
 */
22
23

/*
ken's avatar
ken committed
24
 * Thread IDs are 32 bits.
25
 */
sof's avatar
sof committed
26
typedef StgWord32 StgThreadID;
27

28
#define tsoLocked(tso) ((tso)->flags & TSO_LOCKED)
29

30
/*
31
32
33
 * Type returned after running a thread.  Values of this type
 * include HeapOverflow, StackOverflow etc.  See Constants.h for the
 * full list.
34
 */
35
typedef unsigned int StgThreadReturnCode;
36

37
#if defined(mingw32_HOST_OS)
sof's avatar
sof committed
38
/* results from an async I/O request + its request ID. */
sof's avatar
sof committed
39
40
41
42
43
44
45
typedef struct {
  unsigned int reqID;
  int          len;
  int          errCode;
} StgAsyncIOResult;
#endif

46
/* Reason for thread being blocked. See comment above struct StgTso_. */
47
48
typedef union {
  StgClosure *closure;
49
  StgTSO *prev; // a back-link when the TSO is on the run queue (NotBlocked)
50
  struct MessageBlackHole_ *bh;
51
52
  struct MessageThrowTo_ *throwto;
  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)
sof's avatar
sof committed
55
  StgAsyncIOResult *async_result;
sof's avatar
sof committed
56
#endif
Simon Marlow's avatar
Simon Marlow committed
57
#if !defined(THREADED_RTS)
58
  StgWord target;
Simon Marlow's avatar
Simon Marlow committed
59
    // Only for the non-threaded RTS: the target time for a thread
60
    // blocked in threadDelay, in units of 1ms.  This is a
Simon Marlow's avatar
Simon Marlow committed
61
62
63
    // compromise: we don't want to take up much space in the TSO.  If
    // you want better resolution for threadDelay, use -threaded.
#endif
64
65
} StgTSOBlockInfo;

66

67
68
69
70
71
72
/*
 * TSOs live on the heap, and therefore look just like heap objects.
 * Large TSOs will live in their own "block group" allocated by the
 * storage manager, and won't be copied during garbage collection.
 */

73
/*
74
75
76
77
78
79
80
 * Threads may be blocked for several reasons.  A blocked thread will
 * have the reason in the why_blocked field of the TSO, and some
 * further info (such as the closure the thread is blocked on, or the
 * file descriptor if the thread is waiting on I/O) in the block_info
 * field.
 */

81
typedef struct StgTSO_ {
82
83
    StgHeader               header;

84
85
86
87
88
    /* The link field, for linking threads together in lists (e.g. the
       run queue on a Capability.
    */
    struct StgTSO_*         _link;
    /*
89
90
91
      Currently used for linking TSOs on:
      * cap->run_queue_{hd,tl}
      * (non-THREADED_RTS); the blocked_queue
92
      * and pointing to the next chunk for a ThreadOldStack
93

94
95
96
97
98
99
100
101
102
       NOTE!!!  do not modify _link directly, it is subject to
       a write barrier for generational GC.  Instead use the
       setTSOLink() function.  Exceptions to this rule are:

       * setting the link field to END_TSO_QUEUE
       * setting the link field of the currently running TSO, as it
         will already be dirty.
    */

103
104
    struct StgTSO_*         global_link;    // Links threads on the
                                            // generation->threads lists
105
    
106
107
108
109
110
    /*
     * The thread's stack
     */
    struct StgStack_       *stackobj;

111
112
113
114
115
116
117
118
119
120
121
122
123
124
    /*
     * The tso->dirty flag indicates that this TSO's stack should be
     * scanned during garbage collection.  It also indicates that this
     * TSO is on the mutable list.
     *
     * NB. The dirty flag gets a word to itself, so that it can be set
     * safely by multiple threads simultaneously (the flags field is
     * not safe for this purpose; see #3429).  It is harmless for the
     * TSO to be on the mutable list multiple times.
     *
     * tso->dirty is set by dirty_TSO(), and unset by the garbage
     * collector (only).
     */

125
126
127
    StgWord16               what_next;      // Values defined in Constants.h
    StgWord16               why_blocked;    // Values defined in Constants.h
    StgWord32               flags;          // Values defined in Constants.h
128
129
    StgTSOBlockInfo         block_info;
    StgThreadID             id;
130
131
    StgWord32               saved_errno;
    StgWord32               dirty;          /* non-zero => dirty */
132
    struct InCall_*         bound;
133
    struct Capability_*     cap;
134

135
136
    struct StgTRecHeader_ * trec;       /* STM transaction record */

137
    /*
138
     * A list of threads blocked on this TSO waiting to throw exceptions.
139
    */
140
    struct MessageThrowTo_ * blocked_exceptions;
141

142
    /*
143
144
     * A list of StgBlockingQueue objects, representing threads
     * blocked on thunks that are under evaluation by this thread.
145
146
147
    */
    struct StgBlockingQueue_ *bq;

148
#ifdef TICKY_TICKY
149
    /* TICKY-specific stuff would go here. */
150
151
#endif
#ifdef PROFILING
152
    StgTSOProfInfo prof;
153
#endif
154
155
156
#ifdef mingw32_HOST_OS
    StgWord32 saved_winerror;
#endif
157

158
159
160
161
162
163
164
165
166
167
168
169
170
    /*
     * sum of the sizes of all stack chunks (in words), used to decide
     * whether to throw the StackOverflow exception when the stack
     * overflows, or whether to just chain on another stack chunk.
     *
     * Note that this overestimates the real stack size, because each
     * chunk will have a gap at the end, of +RTS -kb<size> words.
     * This means stack overflows are not entirely accurate, because
     * the more gaps there are, the sooner the stack will run into the
     * hard +RTS -K<size> limit.
     */
    StgWord32  tot_stack_size;

Simon Marlow's avatar
Simon Marlow committed
171
} *StgTSOPtr;
172

173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
typedef struct StgStack_ {
    StgHeader  header;
    StgWord32  stack_size;     // stack size in *words*
    StgWord32  dirty;          // non-zero => dirty
    StgPtr     sp;             // current stack pointer
    StgWord    stack[FLEXIBLE_ARRAY];
} StgStack;

// Calculate SpLim from a TSO (reads tso->stackobj, but no fields from
// the stackobj itself).
INLINE_HEADER StgPtr tso_SpLim (StgTSO* tso)
{
    return tso->stackobj->stack + RESERVED_STACK_WORDS;
}

188
189
190
191
/* -----------------------------------------------------------------------------
   functions
   -------------------------------------------------------------------------- */

Simon Marlow's avatar
Simon Marlow committed
192
193
void dirty_TSO  (Capability *cap, StgTSO *tso);
void setTSOLink (Capability *cap, StgTSO *tso, StgTSO *target);
194
void setTSOPrev (Capability *cap, StgTSO *tso, StgTSO *target);
195

196
void dirty_STACK (Capability *cap, StgStack *stack);
197

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/* -----------------------------------------------------------------------------
   Invariants:

   An active thread has the following properties:

      tso->stack < tso->sp < tso->stack+tso->stack_size
      tso->stack_size <= tso->max_stack_size
      
      RESERVED_STACK_WORDS is large enough for any heap-check or
      stack-check failure.

      The size of the TSO struct plus the stack is either
        (a) smaller than a block, or
	(b) a multiple of BLOCK_SIZE

213
	tso->why_blocked       tso->block_info      location
214
        ----------------------------------------------------------------------
215
	NotBlocked             END_TSO_QUEUE        runnable_queue, or running
216
	
Simon Marlow's avatar
Simon Marlow committed
217
        BlockedOnBlackHole     the BLACKHOLE        blackhole_queue
218
219
	
        BlockedOnMVar          the MVAR             the MVAR's queue
220

Ben Gamari's avatar
Ben Gamari committed
221
222
        BlockedOnSTM           END_TSO_QUEUE        STM wait queue(s)
        BlockedOnSTM           STM_AWOKEN           run queue
223
	
224
        BlockedOnMsgThrowTo    MessageThrowTo *     TSO->blocked_exception
225
226
227
228

        BlockedOnRead          NULL                 blocked_queue
        BlockedOnWrite         NULL		    blocked_queue
        BlockedOnDelay         NULL                 blocked_queue
229
230
	BlockedOnGA            closure TSO blocks on   BQ of that closure
	BlockedOnGA_NoSend     closure TSO blocks on   BQ of that closure
231
232

      tso->link == END_TSO_QUEUE, if the thread is currently running.
233
234
235

   A zombie thread has the following properties:
      
236
      tso->what_next == ThreadComplete or ThreadKilled
237
238
      tso->link     ==  (could be on some queue somewhere)
      tso->sp       ==  tso->stack + tso->stack_size - 1 (i.e. top stack word)
239
240
      tso->sp[0]    ==  return value of thread, if what_next == ThreadComplete,
                        exception             , if what_next == ThreadKilled
241
242
243
244

      (tso->sp is left pointing at the top word on the stack so that
      the return value or exception will be retained by a GC).

245
246
   The 2 cases BlockedOnGA and BlockedOnGA_NoSend are needed in a GUM
   setup only. They mark a TSO that has entered a FETCH_ME or
247
   FETCH_ME_BQ closure, respectively; only the first TSO hitting the
248
249
250
251
   closure will send a Fetch message.
   Currently we have no separate code for blocking on an RBH; we use the
   BlockedOnBlackHole case for that.   -- HWL

252
 ---------------------------------------------------------------------------- */
253

254
255
256
/* this is the NIL ptr for a TSO queue (e.g. runnable queue) */
#define END_TSO_QUEUE  ((StgTSO *)(void*)&stg_END_TSO_QUEUE_closure)

Simon Marlow's avatar
Simon Marlow committed
257
#endif /* RTS_STORAGE_TSO_H */