RTS tidyup sweep, first phase
[ghc-hetmet.git] / rts / STM.h
diff --git a/rts/STM.h b/rts/STM.h
new file mode 100644 (file)
index 0000000..3bf9765
--- /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 */
+