summaryrefslogtreecommitdiff
path: root/includes/TSO.h
blob: 4621d4ad69f1473f913cc8af67956d9b4ef8e032 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/* -----------------------------------------------------------------------------
 *
 * (c) The GHC Team, 1998-1999
 *
 * The definitions for Thread State Objects.
 *
 * ---------------------------------------------------------------------------*/

#ifndef TSO_H
#define TSO_H

#if DEBUG
#define TSO_MAGIC 4321
#endif

typedef struct {
  StgInt   pri;
  StgInt   magic;
  StgInt   sparkname;
  rtsTime  startedat;
  rtsBool  exported;
  StgInt   basicblocks;
  StgInt   allocs;
  rtsTime  exectime;
  rtsTime  fetchtime;
  rtsTime  fetchcount;
  rtsTime  blocktime;
  StgInt   blockcount;
  rtsTime  blockedat;
  StgInt   globalsparks;
  StgInt   localsparks;
  rtsTime  clock;
} StgTSOStatBuf;

/*
 * GRAN: We distinguish between the various classes of threads in 
 * the system.
 */
typedef enum {
  AdvisoryPriority,
  MandatoryPriority,
  RevalPriority
} StgThreadPriority;

/*
 * PROFILING info in a TSO
 */
typedef struct {
  CostCentreStack *CCCS;	/* thread's current CCS */
} StgTSOProfInfo;

/*
 * PAR info in a TSO
 */
typedef StgTSOStatBuf StgTSOParInfo;

/*
 * DIST info in a TSO
 */
typedef struct {
  StgThreadPriority  priority;   
  StgInt             revalTid;   /* ToDo: merge both into 1 word */
  StgInt             revalSlot;
} StgTSODistInfo;

/*
 * GRAN info in a TSO
 */
typedef StgTSOStatBuf StgTSOGranInfo;

/*
 * There is no TICKY info in a TSO at this time.
 */

/*
 * Thread IDs are 32 bits.
 */
typedef StgWord32 StgThreadID;

#define tsoDirty(tso)  ((tso)->flags & TSO_DIRTY)
#define tsoLocked(tso) ((tso)->flags & TSO_LOCKED)

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

#if defined(mingw32_HOST_OS)
/* results from an async I/O request + its request ID. */
typedef struct {
  unsigned int reqID;
  int          len;
  int          errCode;
} StgAsyncIOResult;
#endif

typedef union {
  StgClosure *closure;
  struct StgTSO_ *tso;
  StgInt fd;	/* StgInt instead of int, so that it's the same size as the ptrs */
#if defined(mingw32_HOST_OS)
  StgAsyncIOResult *async_result;
#endif
  StgWord target;
} StgTSOBlockInfo;


/*
 * 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.
 */

/* 
 * 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.
 */

typedef struct StgTSO_ {
    StgHeader               header;

    struct StgTSO_*         link;       /* Links threads onto blocking queues */
    struct StgTSO_*         global_link;    /* Links all threads together */
    
    StgWord16               what_next;      /* Values defined in Constants.h */
    StgWord16               why_blocked;    /* Values defined in Constants.h */
    StgWord32               flags;
    StgTSOBlockInfo         block_info;
    StgThreadID             id;
    int                     saved_errno;
    struct Task_*           bound;
    struct Capability_*     cap;
    struct StgTRecHeader_ * trec;       /* STM transaction record */

    /* 
       A list of threads blocked on this TSO waiting to throw
       exceptions.  In order to access this field, the TSO must be
       locked using lockClosure/unlockClosure (see SMP.h).
    */
    struct StgTSO_ *        blocked_exceptions;

#ifdef TICKY_TICKY
    /* TICKY-specific stuff would go here. */
#endif
#ifdef PROFILING
    StgTSOProfInfo prof;
#endif
#ifdef PAR
    StgTSOParInfo par;
#endif
#ifdef GRAN
    StgTSOGranInfo gran;
#endif
#ifdef DIST
    StgTSODistInfo dist;
#endif

    /* The thread stack... */
    StgWord32	       stack_size;     /* stack size in *words* */
    StgWord32          max_stack_size; /* maximum stack size in *words* */
    StgPtr             sp;
    
    StgWord            stack[FLEXIBLE_ARRAY];
} StgTSO;

/* -----------------------------------------------------------------------------
   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

	tso->why_blocked       tso->block_info      location
        ----------------------------------------------------------------------
	NotBlocked             NULL                 runnable_queue, or running
	
        BlockedOnBlackHole     the BLACKHOLE_BQ     the BLACKHOLE_BQ's queue
	
        BlockedOnMVar          the MVAR             the MVAR's queue

	BlockedOnSTM           END_TSO_QUEUE        STM wait queue(s)
	
        BlockedOnException     the TSO              TSO->blocked_exception

        BlockedOnRead          NULL                 blocked_queue
        BlockedOnWrite         NULL		    blocked_queue
        BlockedOnDelay         NULL                 blocked_queue
	BlockedOnGA            closure TSO blocks on   BQ of that closure
	BlockedOnGA_NoSend     closure TSO blocks on   BQ of that closure

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

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

      (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).

   tso->blocked_exceptions is either:

      NULL             if async exceptions are unblocked.

      END_TSO_QUEUE    if async exceptions are blocked, but no threads
                       are currently waiting to deliver.

      (StgTSO *)tso    if threads are currently awaiting delivery of
                       exceptions to this thread.

   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
   FETCH_ME_BQ closure, respectively; only the first TSO hitting the 
   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

 ---------------------------------------------------------------------------- */

/* Workaround for a bug/quirk in gcc on certain architectures.
 * symptom is that (&tso->stack - &tso->header) /=  sizeof(StgTSO)
 * in other words, gcc pads the structure at the end.
 */

extern StgTSO dummy_tso;

#define TSO_STRUCT_SIZE \
   ((char *)&dummy_tso.stack - (char *)&dummy_tso.header)

#define TSO_STRUCT_SIZEW (TSO_STRUCT_SIZE / sizeof(W_))


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

#if defined(PAR) || defined(GRAN)
/* this is the NIL ptr for a blocking queue */
# define END_BQ_QUEUE  ((StgBlockingQueueElement *)(void*)&stg_END_TSO_QUEUE_closure)
/* this is the NIL ptr for a blocked fetch queue (as in PendingFetches in GUM) */
# define END_BF_QUEUE  ((StgBlockedFetch *)(void*)&stg_END_TSO_QUEUE_closure)
#endif
/* ToDo?: different name for end of sleeping queue ? -- HWL */

#endif /* TSO_H */