1 /*----------------------------------------------------------------------
3 * (c) The GHC Team, 1998-2004
5 * STM interface definition
7 *----------------------------------------------------------------------
9 STM.h defines the C-level interface to the STM.
11 The design follows that of the PPoPP 2005 paper "Composable memory
12 transactions" extended to include fine-grained locking of TVars.
14 Three different implementations can be built. In overview:
16 STM_UNIPROC -- no locking at all: not safe for concurrent invocations
18 STM_CG_LOCK -- coarse-grained locking : a single mutex protects all
21 STM_FG_LOCKS -- per-TVar exclusion : each TVar can be owned by at
22 most one TRec at any time. This allows dynamically
23 non-conflicting transactions to commit in parallel.
24 The implementation treats reads optimisitcally --
25 extra versioning information is retained in the
26 saw_update_by field of the TVars so that they do not
27 need to be locked for reading.
29 STM.C contains more details about the locking schemes used.
47 /*----------------------------------------------------------------------
54 extern void initSTM(void);
56 extern void stmPreGCHook(void);
58 /*----------------------------------------------------------------------
60 Transaction context management
61 ------------------------------
65 /* Create and enter a new transaction context */
67 extern StgTRecHeader *stmStartTransaction(Capability *cap, StgTRecHeader *outer);
68 extern StgTRecHeader *stmStartNestedTransaction(Capability *cap, StgTRecHeader *outer
72 * Exit the current transaction context, abandoning any read/write
73 * operations performed within it and removing the thread from any
74 * tvar wait queues if it was waitin. Note that if nested transactions
75 * are not fully supported then this may leave the enclosing
76 * transaction contexts doomed to abort.
79 extern void stmAbortTransaction(StgTRecHeader *trec);
82 * Ensure that a subsequent commit / validation will fail. We use this
83 * in our current handling of transactions that may have become invalid
84 * and started looping. We strip their stack back to the ATOMICALLY_FRAME,
85 * and, when the thread is next scheduled, discover it to be invalid and
86 * re-execute it. However, we need to force the transaction to stay invalid
87 * in case other threads' updates make it valid in the mean time.
90 extern void stmCondemnTransaction(StgTRecHeader *trec);
93 * Return the trec within which the specified trec was created (not
94 * valid if trec==NO_TREC).
97 extern StgTRecHeader *stmGetEnclosingTRec(StgTRecHeader *trec);
99 /*----------------------------------------------------------------------
104 Test whether the specified transaction record, and all those within which
105 it is nested, are still valid.
107 Note: the caller can assume that once stmValidateTransaction has
108 returned FALSE for a given trec then that transaction will never
109 again be valid -- we rely on this in Schedule.c when kicking invalid
110 threads at GC (in case they are stuck looping)
113 extern StgBool stmValidateNestOfTransactions(StgTRecHeader *trec);
115 /*----------------------------------------------------------------------
117 Commit/wait/rewait operations
118 -----------------------------
120 These four operations return boolean results which should be interpreted
123 true => The transaction record was definitely valid
125 false => The transaction record may not have been valid
127 Note that, for nested operations, validity here is solely in terms
128 of the specified trec: it does not say whether those that it may be
129 nested are themselves valid. Callers can check this with
130 stmValidateNestOfTransactions.
132 The user of the STM should ensure that it is always safe to assume that a
133 transaction context is not valid when in fact it is (i.e. to return false in
134 place of true, with side-effects as defined below). This may cause
135 needless retries of transactions (in the case of validate and commit), or it
136 may cause needless spinning instead of blocking (in the case of wait and
139 In defining the behaviour of wait and rewait we distinguish between two
140 different aspects of a thread's runnability:
142 - We say that a thread is "blocked" when it is not running or
143 runnable as far as the scheduler is concerned.
145 - We say that a thread is "waiting" when its StgTRecHeader is linked on an
148 Considering only STM operations, (blocked) => (waiting). The user of the STM
149 should ensure that they are prepared for threads to be unblocked spuriously
150 and for wait/reWait to return false even when the previous transaction context
151 is actually still valid.
155 * Test whether the current transaction context is valid and, if so,
156 * commit its memory accesses to the heap. stmCommitTransaction must
157 * unblock any threads which are waiting on tvars that updates have
161 extern StgBool stmCommitTransaction(Capability *cap, StgTRecHeader *trec);
162 extern StgBool stmCommitNestedTransaction(Capability *cap, StgTRecHeader *trec);
165 * Test whether the current transaction context is valid and, if so,
166 * start the thread waiting for updates to any of the tvars it has
167 * ready from and mark it as blocked. It is an error to call stmWait
168 * if the thread is already waiting.
171 extern StgBool stmWait(Capability *cap,
173 StgTRecHeader *trec);
176 * Test whether the current transaction context is valid and, if so,
177 * leave the thread waiting and mark it as blocked again. If the
178 * transaction context is no longer valid then stop the thread waiting
179 * and leave it as unblocked. It is an error to call stmReWait if the
180 * thread is not waiting.
183 extern StgBool stmReWait(StgTSO *tso);
185 /*----------------------------------------------------------------------
187 TVar management operations
188 --------------------------
191 extern StgTVar *stmNewTVar(Capability *cap,
192 StgClosure *new_value);
194 /*----------------------------------------------------------------------
196 Data access operations
197 ----------------------
201 * Return the logical contents of 'tvar' within the context of the
202 * thread's current transaction.
205 extern StgClosure *stmReadTVar(Capability *cap,
209 /* Update the logical contents of 'tvar' within the context of the
210 * thread's current transaction.
213 extern void stmWriteTVar(Capability *cap,
216 StgClosure *new_value);
218 /*----------------------------------------------------------------------*/
222 #define END_STM_WAIT_QUEUE ((StgTVarWaitQueue *)(void *)&stg_END_STM_WAIT_QUEUE_closure)
223 #define END_STM_CHUNK_LIST ((StgTRecChunk *)(void *)&stg_END_STM_CHUNK_LIST_closure)
226 #define NO_TREC (stg_NO_TREC_closure)
228 #define NO_TREC ((StgTRecHeader *)(void *)&stg_NO_TREC_closure)
231 /*----------------------------------------------------------------------*/