/* -----------------------------------------------------------------------------
The SMP header
-
- In SMP mode, we have an extra word of padding in a thunk's header.
- (Note: thunks only; other closures do not have this padding word).
+
+ A thunk has a padding word to take the updated value. This is so
+ that the update doesn't overwrite the payload, so we can avoid
+ needing to lock the thunk during entry and update.
+
+ Note: this doesn't apply to THUNK_STATICs, which have no payload.
+
+ Note: we leave this padding word in all ways, rather than just SMP,
+ so that we don't have to recompile all our libraries for SMP.
-------------------------------------------------------------------------- */
typedef struct {
#endif
} StgHeader;
-/*
- * In SMP mode, a thunk has a padding word to take the updated value.
- * This is so that the update doesn't overwrite the payload, so we can
- * avoid needing to lock the thunk during entry and update.
- *
- * Note: this doesn't apply to THUNK_STATICs, which have no payload.
- */
typedef struct {
const struct _StgInfoTable* info;
#ifdef PROFILING
#ifdef GRAN
StgGranHeader gran;
#endif
-#ifdef SMP
StgSMPThunkHeader smp;
-#endif
} StgThunkHeader;
+#define THUNK_EXTRA_HEADER_W (sizeofW(StgThunkHeader)-sizeofW(StgHeader))
+
/* -----------------------------------------------------------------------------
Closure Types
StgHeader header;
} StgRetry;
-typedef struct _StgForeignObj {
- StgHeader header;
- StgAddr data; /* pointer to data in non-haskell-land */
-} StgForeignObj;
-
typedef struct _StgStableName {
StgHeader header;
StgWord sn;
StgClosure* value;
} StgMVar;
+
/* STM data structures
*
* StgTVar defines the only type that can be updated through the STM
* - 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.
+ *
+ * - In StgAtomicallyFrame, we could combine the waiting bit into
+ * the header (maybe a different info tbl for a waiting transaction).
+ * This means we can specialise the code for the atomically frame
+ * (it immediately switches on frame->waiting anyway).
*/
typedef struct StgTVarWaitQueue_ {
typedef struct {
StgHeader header;
- StgClosure *current_value;
- StgTVarWaitQueue *first_wait_queue_entry;
+ 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 */
StgTVar *tvar;
StgClosure *expected_value;
StgClosure *new_value;
+#if defined(THREADED_RTS)
+ StgInt num_updates;
+#endif
} TRecEntry;
-#define TREC_CHUNK_NUM_ENTRIES 256
+#define TREC_CHUNK_NUM_ENTRIES 16
typedef struct StgTRecChunk_ {
StgHeader header;
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_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 */
typedef struct {
StgHeader header;
- StgBool waiting;
StgClosure *code;
} StgAtomicallyFrame;