/* ----------------------------------------------------------------------------
- * $Id: Closures.h,v 1.33 2003/03/24 14:46:53 simonmar Exp $
*
- * (c) The GHC Team, 1998-1999
+ * (c) The GHC Team, 1998-2004
*
* Closures
*
#endif
} StgHeader;
-#define FIXED_HS (sizeof(StgHeader))
-
/* -----------------------------------------------------------------------------
Closure Types
#define BCO_BITMAP_SIZEW(bco) ((BCO_BITMAP_SIZE(bco) + BITS_IN(StgWord) - 1) \
/ BITS_IN(StgWord))
-/* Dynamic stack frames - these have a liveness mask in the object
- * itself, rather than in the info table. Useful for generic heap
- * check code. See StgMacros.h, HEAP_CHK_GEN().
- */
-
+/* -----------------------------------------------------------------------------
+ Dynamic stack frames for generic heap checks.
+
+ These generic heap checks are slow, but have the advantage of being
+ usable in a variety of situations.
+
+ The one restriction is that any relevant SRTs must already be pointed
+ to from the stack. The return address doesn't need to have an info
+ table attached: hence it can be any old code pointer.
+
+ The liveness mask contains a 1 at bit n, if register Rn contains a
+ non-pointer. The contents of all 8 vanilla registers are always saved
+ on the stack; the liveness mask tells the GC which ones contain
+ pointers.
+
+ Good places to use a generic heap check:
+
+ - case alternatives (the return address with an SRT is already
+ on the stack).
+
+ - primitives (no SRT required).
+
+ The stack frame layout for a RET_DYN is like this:
+
+ some pointers |-- RET_DYN_PTRS(liveness) words
+ some nonpointers |-- RET_DYN_NONPTRS(liveness) words
+
+ L1 \
+ D1-2 |-- RET_DYN_NONPTR_REGS_SIZE words
+ F1-4 /
+
+ R1-8 |-- RET_DYN_BITMAP_SIZE words
+
+ return address \
+ liveness mask |-- StgRetDyn structure
+ stg_gen_chk_info /
+
+ we assume that the size of a double is always 2 pointers (wasting a
+ word when it is only one pointer, but avoiding lots of #ifdefs).
+
+ See Liveness.h for the macros (RET_DYN_PTRS() etc.).
+
+ NOTE: if you change the layout of RET_DYN stack frames, then you
+ might also need to adjust the value of RESERVED_STACK_WORDS in
+ Constants.h.
+ -------------------------------------------------------------------------- */
+
typedef struct {
const struct _StgInfoTable* info;
StgWord liveness;
StgClosure* value;
} StgMVar;
+/* STM data structures
+ *
+ * StgTVar defines the only type that can be updated through the STM
+ * interface.
+ *
+ * Note that various optimisations may be possible in order to use less
+ * space for these data structures at the cost of more complexity in the
+ * implementation:
+ *
+ * - In StgTVar, current_value and first_wait_queue_entry could be held in
+ * the same field: if any thread is waiting then its expected_value for
+ * the tvar is the current value.
+ *
+ * - In StgTRecHeader, it might be worthwhile having separate chunks
+ * of read-only and read-write locations. This would save a
+ * new_value field in the read-only locations.
+ */
+
+typedef struct StgTVarWaitQueue_ {
+ StgHeader header;
+ struct StgTSO_ *waiting_tso;
+ StgMutClosure *mut_link;
+ struct StgTVarWaitQueue_ *next_queue_entry;
+ struct StgTVarWaitQueue_ *prev_queue_entry;
+} StgTVarWaitQueue;
+
+typedef struct {
+ StgHeader header;
+ StgClosure *current_value;
+ StgMutClosure *mut_link;
+ StgTVarWaitQueue *first_wait_queue_entry;
+} StgTVar;
+
+// new_value == expected_value for read-only accesses
+// new_value is a StgTVarWaitQueue entry when trec in state TREC_WAITING
+typedef struct {
+ StgTVar *tvar;
+ StgClosure *expected_value;
+ StgClosure *new_value;
+} TRecEntry;
+
+#define TREC_CHUNK_NUM_ENTRIES 256
+
+typedef struct StgTRecChunk_ {
+ StgHeader header;
+ struct StgTRecChunk_ *prev_chunk;
+ StgMutClosure *mut_link;
+ StgWord next_entry_idx;
+ TRecEntry entries[TREC_CHUNK_NUM_ENTRIES];
+} StgTRecChunk;
+
+typedef enum {
+ TREC_ACTIVE, // Transaction in progress, outcome undecided
+ TREC_CANNOT_COMMIT, // Transaction in progress, inconsistent writes performed
+ TREC_MUST_ABORT, // Transaction in progress, inconsistent / out of date reads
+ TREC_COMMITTED, // Transaction has committed, now updating tvars
+ TREC_ABORTED, // Transaction has aborted, now reverting tvars
+ TREC_WAITING, // Transaction currently waiting
+} TRecState;
+
+typedef struct StgTRecHeader_ {
+ StgHeader header;
+ TRecState state;
+ StgMutClosure *mut_link;
+ struct StgTRecHeader_ *enclosing_trec;
+ StgTRecChunk *current_chunk;
+} StgTRecHeader;
+
+typedef struct {
+ StgHeader header;
+ StgBool waiting;
+ StgClosure *code;
+} StgAtomicallyFrame;
+
+typedef struct {
+ StgHeader header;
+ StgClosure *handler;
+} StgCatchSTMFrame;
+
+typedef struct {
+ StgHeader header;
+ StgBool running_alt_code;
+ StgClosure *first_code;
+ StgClosure *alt_code;
+ StgTRecHeader *first_code_trec;
+} StgCatchRetryFrame;
+
#if defined(PAR) || defined(GRAN)
/*
StgBlockingQueueElement is a ``collective type'' representing the types