+ StgHeader header;
+ StgClosure *volatile current_value;
+ StgTVarWaitQueue *volatile first_wait_queue_entry;
+#if defined(THREADED_RTS)
+ StgInt volatile num_updates;
+#endif
+} 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;
+#if defined(THREADED_RTS)
+ StgInt num_updates;
+#endif
+} TRecEntry;
+
+#define TREC_CHUNK_NUM_ENTRIES 16
+
+typedef struct StgTRecChunk_ {
+ StgHeader header;
+ struct StgTRecChunk_ *prev_chunk;
+ StgWord next_entry_idx;
+ TRecEntry entries[TREC_CHUNK_NUM_ENTRIES];
+} StgTRecChunk;
+
+typedef enum {
+ TREC_ACTIVE, /* Transaction in progress, outcome undecided */
+ TREC_CONDEMNED, /* 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;
+ struct StgTRecHeader_ *enclosing_trec;
+ StgTRecChunk *current_chunk;
+} StgTRecHeader;
+
+typedef struct {
+ StgHeader header;
+ 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
+ of closures that can be found on a blocking queue: StgTSO, StgRBHSave,
+ StgBlockedFetch. (StgRBHSave can only appear at the end of a blocking
+ queue). Logically, this is a union type, but defining another struct
+ with a common layout is easier to handle in the code.
+ Note that in the standard setup only StgTSOs can be on a blocking queue.
+ This is one of the main reasons for slightly different code in files
+ such as Schedule.c.
+*/
+typedef struct StgBlockingQueueElement_ {
+ StgHeader header;
+ struct StgBlockingQueueElement_ *link; /* next elem in BQ */
+ struct StgClosure_ *payload[FLEXIBLE_ARRAY];/* contents of the closure */
+} StgBlockingQueueElement;
+
+/* only difference to std code is type of the elem in the BQ */
+typedef struct StgBlockingQueue_ {
+ StgHeader header;
+ struct StgBlockingQueueElement_ *blocking_queue; /* start of the BQ */
+} StgBlockingQueue;
+
+/* this closure is hanging at the end of a blocking queue in (see RBH.c) */
+typedef struct StgRBHSave_ {