TSO.h 7.45 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 16 17 18
typedef struct {
  CostCentreStack *CCCS;	/* thread's current CCS */
} 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
  struct StgTSO_ *tso;
50
  StgInt fd;	/* StgInt instead of int, so that it's the same size as the ptrs */
51
#if defined(mingw32_HOST_OS)
sof's avatar
sof committed
52
  StgAsyncIOResult *async_result;
sof's avatar
sof committed
53
#endif
54
  StgWord target;
55 56
} StgTSOBlockInfo;

57

58 59 60 61 62 63
/*
 * 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.
 */

64
/*
65 66 67 68 69 70 71
 * 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.
 */

72
typedef struct StgTSO_ {
73 74
    StgHeader               header;

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
    /* The link field, for linking threads together in lists (e.g. the
       run queue on a Capability.
    */
    struct StgTSO_*         _link;
    /*
       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
       * putting a TSO on the blackhole_queue
       * setting the link field of the currently running TSO, as it
         will already be dirty.
    */

90 91
    struct StgTSO_*         global_link;    /* Links all threads together */
    
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
    StgWord                 dirty;          /* non-zero => dirty */
    /*
     * 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).
     *
     * The link field has a separate dirty bit of its own, namely the
     * bit TSO_LINK_DIRTY in the tso->flags field, set by
     * setTSOLink().
     */

111 112 113 114 115 116 117 118 119 120
    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 */

121
    /*
122 123 124 125 126 127
       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;

128
#ifdef TICKY_TICKY
129
    /* TICKY-specific stuff would go here. */
130 131
#endif
#ifdef PROFILING
132
    StgTSOProfInfo prof;
133
#endif
134 135 136
#ifdef mingw32_HOST_OS
    StgWord32 saved_winerror;
#endif
137

138 139 140 141 142 143
    /* 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];
Simon Marlow's avatar
Simon Marlow committed
144
} *StgTSOPtr;
145

146 147 148 149
/* -----------------------------------------------------------------------------
   functions
   -------------------------------------------------------------------------- */

Simon Marlow's avatar
Simon Marlow committed
150 151
void dirty_TSO  (Capability *cap, StgTSO *tso);
void setTSOLink (Capability *cap, StgTSO *tso, StgTSO *target);
152

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
/* -----------------------------------------------------------------------------
   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

168
	tso->why_blocked       tso->block_info      location
169 170 171
        ----------------------------------------------------------------------
	NotBlocked             NULL                 runnable_queue, or running
	
Simon Marlow's avatar
Simon Marlow committed
172
        BlockedOnBlackHole     the BLACKHOLE        blackhole_queue
173 174
	
        BlockedOnMVar          the MVAR             the MVAR's queue
175 176

	BlockedOnSTM           END_TSO_QUEUE        STM wait queue(s)
177 178 179 180 181 182
	
        BlockedOnException     the TSO              TSO->blocked_exception

        BlockedOnRead          NULL                 blocked_queue
        BlockedOnWrite         NULL		    blocked_queue
        BlockedOnDelay         NULL                 blocked_queue
183 184
	BlockedOnGA            closure TSO blocks on   BQ of that closure
	BlockedOnGA_NoSend     closure TSO blocks on   BQ of that closure
185 186

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

   A zombie thread has the following properties:
      
190
      tso->what_next == ThreadComplete or ThreadKilled
191 192 193
      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)
194 195
      tso->sp[0]    ==  return value of thread, if what_next == ThreadComplete,
                        exception             , if what_next == ThreadKilled
196 197 198 199

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

200 201
   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
202
   FETCH_ME_BQ closure, respectively; only the first TSO hitting the
203 204 205 206
   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

207
 ---------------------------------------------------------------------------- */
208 209 210 211 212 213 214 215 216

/* 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 \
217
   ((char *)&dummy_tso.stack - (char *)&dummy_tso.header)
218 219 220

#define TSO_STRUCT_SIZEW (TSO_STRUCT_SIZE / sizeof(W_))

221 222 223
/* 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
224
#endif /* RTS_STORAGE_TSO_H */