ebbf193b0b661699b4a1d52689a62ce98b7d9958
[ghc-hetmet.git] / includes / STM.h
1 /*----------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2004
4  *
5  * STM interface definition
6  *
7  *----------------------------------------------------------------------
8
9   STM.h defines the C-level interface to the STM.  
10
11   The design follows that of the PPoPP 2005 paper "Composable memory
12   transactions" extended to include fine-grained locking of TVars.
13
14   Three different implementations can be built.  In overview:
15   
16   STM_UNIPROC  -- no locking at all: not safe for concurrent invocations
17  
18   STM_CG_LOCK  -- coarse-grained locking : a single mutex protects all
19                   TVars
20  
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.
28
29   STM.C contains more details about the locking schemes used.
30
31 */
32
33 #ifndef STM_H
34 #define STM_H
35
36 #ifdef THREADED_RTS
37 //#define STM_CG_LOCK
38 #define STM_FG_LOCKS
39 #else
40 #define STM_UNIPROC
41 #endif
42
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46
47 /*----------------------------------------------------------------------
48
49    GC interaction
50    --------------
51 */
52
53 extern void stmPreGCHook(void);
54
55 /*----------------------------------------------------------------------
56
57    Transaction context management
58    ------------------------------
59
60 */
61
62 /* Create and enter a new transaction context */
63
64 extern StgTRecHeader *stmStartTransaction(Capability *cap, StgTRecHeader *outer);
65 extern StgTRecHeader *stmStartNestedTransaction(Capability *cap, StgTRecHeader *outer
66 );
67
68 /*
69  * Exit the current transaction context, abandoning any read/write
70  * operations performed within it and removing the thread from any
71  * tvar wait queues if it was waitin.  Note that if nested transactions
72  * are not fully supported then this may leave the enclosing
73  * transaction contexts doomed to abort.
74  */
75
76 extern void stmAbortTransaction(Capability *cap, StgTRecHeader *trec);
77
78 /*
79  * Ensure that a subsequent commit / validation will fail.  We use this 
80  * in our current handling of transactions that may have become invalid
81  * and started looping.  We strip their stack back to the ATOMICALLY_FRAME,
82  * and, when the thread is next scheduled, discover it to be invalid and
83  * re-execute it.  However, we need to force the transaction to stay invalid
84  * in case other threads' updates make it valid in the mean time.
85  */
86
87 extern void stmCondemnTransaction(Capability *cap, StgTRecHeader *trec);
88
89 /*
90  * Return the trec within which the specified trec was created (not
91  * valid if trec==NO_TREC).
92  */
93
94 extern StgTRecHeader *stmGetEnclosingTRec(StgTRecHeader *trec);
95
96 /*----------------------------------------------------------------------
97
98    Validation
99    ----------
100
101   Test whether the specified transaction record, and all those within which
102   it is nested, are still valid.
103
104   Note: the caller can assume that once stmValidateTransaction has
105   returned FALSE for a given trec then that transaction will never
106   again be valid -- we rely on this in Schedule.c when kicking invalid
107   threads at GC (in case they are stuck looping)
108 */
109
110 extern StgBool stmValidateNestOfTransactions(StgTRecHeader *trec);
111
112 /*----------------------------------------------------------------------
113
114    Commit/wait/rewait operations
115    -----------------------------
116
117    These four operations return boolean results which should be interpreted
118    as follows:
119
120    true  => The transaction record was definitely valid 
121
122    false => The transaction record may not have been valid
123
124    Note that, for nested operations, validity here is solely in terms
125    of the specified trec: it does not say whether those that it may be
126    nested are themselves valid.  Callers can check this with 
127    stmValidateNestOfTransactions.
128
129    The user of the STM should ensure that it is always safe to assume that a
130    transaction context is not valid when in fact it is (i.e. to return false in
131    place of true, with side-effects as defined below).  This may cause
132    needless retries of transactions (in the case of validate and commit), or it
133    may cause needless spinning instead of blocking (in the case of wait and
134    rewait).
135
136    In defining the behaviour of wait and rewait we distinguish between two
137    different aspects of a thread's runnability:
138
139     - We say that a thread is "blocked" when it is not running or
140       runnable as far as the scheduler is concerned.
141
142     - We say that a thread is "waiting" when its StgTRecHeader is linked on an
143       tvar's wait queue.
144
145    Considering only STM operations, (blocked) => (waiting).  The user of the STM
146    should ensure that they are prepared for threads to be unblocked spuriously
147    and for wait/reWait to return false even when the previous transaction context
148    is actually still valid.
149 */
150
151 /*
152  * Test whether the current transaction context is valid and, if so,
153  * commit its memory accesses to the heap.  stmCommitTransaction must
154  * unblock any threads which are waiting on tvars that updates have
155  * been committed to.
156  */
157
158 extern StgBool stmCommitTransaction(Capability *cap, StgTRecHeader *trec);
159 extern StgBool stmCommitNestedTransaction(Capability *cap, StgTRecHeader *trec);
160
161 /*
162  * Test whether the current transaction context is valid and, if so,
163  * start the thread waiting for updates to any of the tvars it has
164  * ready from and mark it as blocked.  It is an error to call stmWait
165  * if the thread is already waiting.  
166  */
167
168 extern StgBool stmWait(Capability *cap,
169                        StgTSO *tso, 
170                        StgTRecHeader *trec);
171
172 extern void stmWaitUnlock(Capability *cap, StgTRecHeader *trec);
173
174 /*
175  * Test whether the current transaction context is valid and, if so,
176  * leave the thread waiting and mark it as blocked again.  If the
177  * transaction context is no longer valid then stop the thread waiting
178  * and leave it as unblocked.  It is an error to call stmReWait if the
179  * thread is not waiting.
180  */
181
182 extern StgBool stmReWait(Capability *cap, StgTSO *tso);
183
184 /*----------------------------------------------------------------------
185
186    TVar management operations
187    --------------------------
188 */
189
190 extern StgTVar *stmNewTVar(Capability *cap,
191                            StgClosure *new_value);
192
193 /*----------------------------------------------------------------------
194
195    Data access operations
196    ----------------------
197 */
198
199 /*
200  * Return the logical contents of 'tvar' within the context of the
201  * thread's current transaction.
202  */
203
204 extern StgClosure *stmReadTVar(Capability *cap,
205                                StgTRecHeader *trec, 
206                                StgTVar *tvar);
207
208 /* Update the logical contents of 'tvar' within the context of the
209  * thread's current transaction.
210  */
211
212 extern void stmWriteTVar(Capability *cap,
213                          StgTRecHeader *trec,
214                          StgTVar *tvar, 
215                          StgClosure *new_value);
216
217 /*----------------------------------------------------------------------*/
218
219 /* NULLs */
220
221 #define END_STM_WAIT_QUEUE ((StgTVarWaitQueue *)(void *)&stg_END_STM_WAIT_QUEUE_closure)
222 #define END_STM_CHUNK_LIST ((StgTRecChunk *)(void *)&stg_END_STM_CHUNK_LIST_closure)
223
224 #define NO_TREC ((StgTRecHeader *)(void *)&stg_NO_TREC_closure)
225
226 /*----------------------------------------------------------------------*/
227
228 #ifdef __cplusplus
229 }
230 #endif
231
232 #endif /* STM_H */
233