summaryrefslogtreecommitdiff
path: root/rts/STM.h
diff options
context:
space:
mode:
Diffstat (limited to 'rts/STM.h')
-rw-r--r--rts/STM.h245
1 files changed, 245 insertions, 0 deletions
diff --git a/rts/STM.h b/rts/STM.h
new file mode 100644
index 0000000000..3bf976551d
--- /dev/null
+++ b/rts/STM.h
@@ -0,0 +1,245 @@
+/*----------------------------------------------------------------------
+ *
+ * (c) The GHC Team, 1998-2004
+ *
+ * STM interface definition
+ *
+ *----------------------------------------------------------------------
+
+ STM.h defines the C-level interface to the STM.
+
+ The design follows that of the PPoPP 2005 paper "Composable memory
+ transactions" extended to include fine-grained locking of TVars.
+
+ Three different implementations can be built. In overview:
+
+ STM_UNIPROC -- no locking at all: not safe for concurrent invocations
+
+ STM_CG_LOCK -- coarse-grained locking : a single mutex protects all
+ TVars
+
+ STM_FG_LOCKS -- per-TVar exclusion : each TVar can be owned by at
+ most one TRec at any time. This allows dynamically
+ non-conflicting transactions to commit in parallel.
+ The implementation treats reads optimisitcally --
+ extra versioning information is retained in the
+ saw_update_by field of the TVars so that they do not
+ need to be locked for reading.
+
+ STM.C contains more details about the locking schemes used.
+
+*/
+
+#ifndef STM_H
+#define STM_H
+
+#ifdef THREADED_RTS
+//#define STM_CG_LOCK
+#define STM_FG_LOCKS
+#else
+#define STM_UNIPROC
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------------------------------------
+
+ GC interaction
+ --------------
+*/
+
+extern void stmPreGCHook(void);
+
+/*----------------------------------------------------------------------
+
+ Transaction context management
+ ------------------------------
+
+*/
+
+/* Create and enter a new transaction context */
+
+extern StgTRecHeader *stmStartTransaction(Capability *cap, StgTRecHeader *outer);
+extern StgTRecHeader *stmStartNestedTransaction(Capability *cap, StgTRecHeader *outer
+);
+
+/*
+ * Roll back the current transatcion context. NB: if this is a nested tx
+ * then we merge its read set into its parents. This is because a change
+ * to that read set could change whether or not the tx should abort.
+ */
+
+extern void stmAbortTransaction(Capability *cap, StgTRecHeader *trec);
+extern void stmFreeAbortedTRec(Capability *cap, StgTRecHeader *trec);
+
+/*
+ * Ensure that a subsequent commit / validation will fail. We use this
+ * in our current handling of transactions that may have become invalid
+ * and started looping. We strip their stack back to the ATOMICALLY_FRAME,
+ * and, when the thread is next scheduled, discover it to be invalid and
+ * re-execute it. However, we need to force the transaction to stay invalid
+ * in case other threads' updates make it valid in the mean time.
+ */
+
+extern void stmCondemnTransaction(Capability *cap, StgTRecHeader *trec);
+
+/*
+ * Return the trec within which the specified trec was created (not
+ * valid if trec==NO_TREC).
+ */
+
+extern StgTRecHeader *stmGetEnclosingTRec(StgTRecHeader *trec);
+
+/*----------------------------------------------------------------------
+
+ Validation
+ ----------
+
+ Test whether the specified transaction record, and all those within which
+ it is nested, are still valid.
+
+ Note: the caller can assume that once stmValidateTransaction has
+ returned FALSE for a given trec then that transaction will never
+ again be valid -- we rely on this in Schedule.c when kicking invalid
+ threads at GC (in case they are stuck looping)
+*/
+
+extern StgBool stmValidateNestOfTransactions(StgTRecHeader *trec);
+
+/*----------------------------------------------------------------------
+
+ Commit/wait/rewait operations
+ -----------------------------
+
+ These four operations return boolean results which should be interpreted
+ as follows:
+
+ true => The transaction record was definitely valid
+
+ false => The transaction record may not have been valid
+
+ Note that, for nested operations, validity here is solely in terms
+ of the specified trec: it does not say whether those that it may be
+ nested are themselves valid. Callers can check this with
+ stmValidateNestOfTransactions.
+
+ The user of the STM should ensure that it is always safe to assume that a
+ transaction context is not valid when in fact it is (i.e. to return false in
+ place of true, with side-effects as defined below). This may cause
+ needless retries of transactions (in the case of validate and commit), or it
+ may cause needless spinning instead of blocking (in the case of wait and
+ rewait).
+
+ In defining the behaviour of wait and rewait we distinguish between two
+ different aspects of a thread's runnability:
+
+ - We say that a thread is "blocked" when it is not running or
+ runnable as far as the scheduler is concerned.
+
+ - We say that a thread is "waiting" when its StgTRecHeader is linked on an
+ tvar's wait queue.
+
+ Considering only STM operations, (blocked) => (waiting). The user of the STM
+ should ensure that they are prepared for threads to be unblocked spuriously
+ and for wait/reWait to return false even when the previous transaction context
+ is actually still valid.
+*/
+
+/*
+ * Fill in the trec's list of invariants that might be violated by the current
+ * transaction.
+ */
+
+extern StgInvariantCheckQueue *stmGetInvariantsToCheck(Capability *cap,
+ StgTRecHeader *trec);
+
+extern void stmAddInvariantToCheck(Capability *cap,
+ StgTRecHeader *trec,
+ StgClosure *code);
+
+/*
+ * Test whether the current transaction context is valid and, if so,
+ * commit its memory accesses to the heap. stmCommitTransaction must
+ * unblock any threads which are waiting on tvars that updates have
+ * been committed to.
+ */
+
+extern StgBool stmCommitTransaction(Capability *cap, StgTRecHeader *trec);
+extern StgBool stmCommitNestedTransaction(Capability *cap, StgTRecHeader *trec);
+
+/*
+ * Test whether the current transaction context is valid and, if so,
+ * start the thread waiting for updates to any of the tvars it has
+ * ready from and mark it as blocked. It is an error to call stmWait
+ * if the thread is already waiting.
+ */
+
+extern StgBool stmWait(Capability *cap,
+ StgTSO *tso,
+ StgTRecHeader *trec);
+
+extern void stmWaitUnlock(Capability *cap, StgTRecHeader *trec);
+
+/*
+ * Test whether the current transaction context is valid and, if so,
+ * leave the thread waiting and mark it as blocked again. If the
+ * transaction context is no longer valid then stop the thread waiting
+ * and leave it as unblocked. It is an error to call stmReWait if the
+ * thread is not waiting.
+ */
+
+extern StgBool stmReWait(Capability *cap, StgTSO *tso);
+
+/*----------------------------------------------------------------------
+
+ TVar management operations
+ --------------------------
+*/
+
+extern StgTVar *stmNewTVar(Capability *cap,
+ StgClosure *new_value);
+
+/*----------------------------------------------------------------------
+
+ Data access operations
+ ----------------------
+*/
+
+/*
+ * Return the logical contents of 'tvar' within the context of the
+ * thread's current transaction.
+ */
+
+extern StgClosure *stmReadTVar(Capability *cap,
+ StgTRecHeader *trec,
+ StgTVar *tvar);
+
+/* Update the logical contents of 'tvar' within the context of the
+ * thread's current transaction.
+ */
+
+extern void stmWriteTVar(Capability *cap,
+ StgTRecHeader *trec,
+ StgTVar *tvar,
+ StgClosure *new_value);
+
+/*----------------------------------------------------------------------*/
+
+/* NULLs */
+
+#define END_STM_WATCH_QUEUE ((StgTVarWatchQueue *)(void *)&stg_END_STM_WATCH_QUEUE_closure)
+#define END_INVARIANT_CHECK_QUEUE ((StgInvariantCheckQueue *)(void *)&stg_END_INVARIANT_CHECK_QUEUE_closure)
+#define END_STM_CHUNK_LIST ((StgTRecChunk *)(void *)&stg_END_STM_CHUNK_LIST_closure)
+
+#define NO_TREC ((StgTRecHeader *)(void *)&stg_NO_TREC_closure)
+
+/*----------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* STM_H */
+