/* -----------------------------------------------------------------------------
- * $Id: TSO.h,v 1.6 1999/03/16 13:20:10 simonm Exp $
+ * $Id: TSO.h,v 1.9 1999/12/01 14:34:49 simonmar Exp $
*
* (c) The GHC Team, 1998-1999
*
} StgTSOParInfo;
#endif /* PAR */
-#if defined(TICKY)
+#if defined(TICKY_TICKY)
typedef struct {
} StgTSOTickyInfo;
-#else /* !TICKY */
+#else /* !TICKY_TICKY */
typedef struct {
} StgTSOTickyInfo;
-#endif /* TICKY */
+#endif /* TICKY_TICKY */
typedef enum {
tso_state_runnable,
ThreadFinished
} StgThreadReturnCode;
+/*
+ * 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 enum {
+ NotBlocked,
+ BlockedOnMVar,
+ BlockedOnBlackHole,
+ BlockedOnException,
+ BlockedOnRead,
+ BlockedOnWrite,
+ BlockedOnDelay
+} StgTSOBlockReason;
+
+typedef union {
+ StgClosure *closure;
+ struct StgTSO_ *tso;
+ int fd;
+ unsigned int delay;
+} 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
struct StgTSO_* link;
StgMutClosure * mut_link; /* TSO's are mutable of course! */
StgTSOWhatNext whatNext;
- StgClosure * blocked_on;
+ StgTSOBlockReason why_blocked;
+ StgTSOBlockInfo block_info;
+ struct StgTSO_* blocked_exceptions;
StgThreadID id;
StgTSOTickyInfo ticky;
StgTSOProfInfo prof;
StgWord stack[0];
} StgTSO;
-extern DLL_IMPORT_RTS StgTSO *CurrentTSO;
-
/* -----------------------------------------------------------------------------
Invariants:
(a) smaller than a block, or
(b) a multiple of BLOCK_SIZE
- tso->link
- == END_TSO_QUEUE , iff the thread is currently running.
- == (StgTSO *) , otherwise, and it is linked onto either:
+ tso->block_reason 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
+
+ BlockedOnException the TSO TSO->blocked_exception
+
+ BlockedOnRead NULL blocked_queue
+ BlockedOnWrite NULL blocked_queue
+ BlockedOnDelay NULL blocked_queue
+
+ tso->link == END_TSO_QUEUE, if the thread is currently running.
- - the runnable_queue tso->blocked_on == END_TSO_QUEUE
- - the blocked_queue tso->blocked_on == END_TSO_QUEUE
- - a BLACKHOLE_BQ, tso->blocked_on == the BLACKHOLE_BQ
- - an MVAR, tso->blocked_on == the MVAR
-
A zombie thread has the following properties:
tso->whatNext == ThreadComplete or 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.
+
+ ---------------------------------------------------------------------------- */
/* Workaround for a bug/quirk in gcc on certain architectures.
* symptom is that (&tso->stack - &tso->header) /= sizeof(StgTSO)