[project @ 2005-03-27 13:41:13 by panne]
[ghc-hetmet.git] / ghc / 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 interface is designed so that all of the operations return
12   directly: if the specified StgTSO should block then the Haskell
13   scheduler's data structures are updated within the STM
14   implementation, rather than blocking the native thread.
15
16   This interface can be supported by many different implementations,
17   in particular it is left unspecified:
18
19    - Whether nested transactions are fully supported.
20  
21      A simple implementation would count the number of
22      stmStartTransaction operations that a thread invokes and only
23      attempt to really commit it to the heap when the corresponding
24      number of stmCommitTransaction calls have been made.  This
25      prevents enclosed transactions from being aborted without also
26      aborting all of the outer ones.  
27  
28      The current implementation does support proper nesting.
29
30    - Whether stmWait and stmReWait are blocking.
31
32      A simple implementation would always return 'false' from these
33      operations, signalling that the calling thread should immediately
34      retry its transaction.
35
36      A fuller implementation would block the thread and return 'True'
37      when it is safe for the thread to block.
38
39      The current implementation does provide stmWait and stmReWait 
40      operations which can block the caller's TSO.
41
42    - Whether the transactional read, write, commit and validate
43      operations are blocking or non-blocking.
44
45      A simple implementation would use an internal lock to prevent
46      concurrent execution of any STM operations.  (This does not
47      prevent multiple threads having concurrent transactions, merely
48      the concurrent execution of say stmCommitTransaction by two
49      threads at the same time). 
50
51      A fuller implementation would offer obstruction-free or lock-free
52      progress guarantees, as in our OOPSLA 2003 paper.
53
54      The current implementation is lock-free for simple uncontended
55      operations, but uses an internal lock on SMP systems in some
56      cases.  This aims to provide good performance on uniprocessors:
57      it substantially streamlines the design, when compared with the
58      OOPSLA paper, and on a uniprocessor we can be sure that threads
59      are never pre-empted within STM operations.
60 */
61
62 #ifndef STM_H
63 #define STM_H
64
65 #ifdef __cplusplus
66 extern "C" {
67 #endif
68
69 /*----------------------------------------------------------------------
70
71    Start of day
72    ------------
73
74 */
75
76 extern void initSTM(void);
77
78 extern void stmPreGCHook(void);
79
80 /*----------------------------------------------------------------------
81
82    Transaction context management
83    ------------------------------
84
85 */
86
87 /* Create and enter a new transaction context */
88
89 extern StgTRecHeader *stmStartTransaction(StgTRecHeader *outer);
90
91 /*
92  * Exit the current transaction context, abandoning any read/write
93  * operations performed within it and removing the thread from any
94  * tvar wait queues if it was waitin.  Note that if nested transactions
95  * are not fully supported then this may leave the enclosing
96  * transaction contexts doomed to abort.
97  */
98
99 extern void stmAbortTransaction(StgTRecHeader *trec);
100
101 /*
102  * Ensure that a subsequent commit / validation will fail.  We use this 
103  * in our current handling of transactions that may have become invalid
104  * and started looping.  We strip their stack back to the ATOMICALLY_FRAME,
105  * and, when the thread is next scheduled, discover it to be invalid and
106  * re-execute it.  However, we need to force the transaction to stay invalid
107  * in case other threads' updates make it valid in the mean time.
108  */
109
110 extern void stmCondemnTransaction(StgTRecHeader *trec);
111
112 /*
113  * Return the trec within which the specified trec was created (not
114  * valid if trec==NO_TREC).
115  */
116
117 extern StgTRecHeader *stmGetEnclosingTRec(StgTRecHeader *trec);
118
119 /*----------------------------------------------------------------------
120
121    Validate/commit/wait/rewait operations
122    --------------------------------------
123
124
125    These four operations return boolean results which should be interpreted
126    as follows:
127
128    true  => The transaction context was definitely valid 
129
130    false => The transaction context may not have been valid
131
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
137    rewait).
138
139    In defining the behaviour of wait and rewait we distinguish between two
140    different aspects of a thread's runnability:
141
142     - We say that a thread is "blocked" when it is not running or
143       runnable as far as the scheduler is concerned.
144
145     - We say that a thread is "waiting" when its StgTRecHeader is linked on an
146       tvar's wait queue.
147
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.
152 */
153
154 /*
155  * Test whether the current transaction context is valid, i.e. whether
156  * it is still possible for it to commit successfully.  Note: we assume that
157  * once stmValidateTransaction has returned FALSE for a given transaction then
158  * that transaction will never again be valid -- we rely on this in Schedule.c when
159  * kicking invalid threads at GC (in case they are stuck looping)
160  */
161
162 extern StgBool stmValidateTransaction(StgTRecHeader *trec);
163
164 /*
165  * Test whether the current transaction context is valid and, if so,
166  * commit its memory accesses to the heap.  stmCommitTransaction must
167  * unblock any threads which are waiting on tvars that updates have
168  * been committed to.
169  */
170
171 extern StgBool stmCommitTransaction(StgTRecHeader *trec);
172
173 /*
174  * Test whether the current transaction context is valid and, if so,
175  * start the thread waiting for updates to any of the tvars it has
176  * ready from and mark it as blocked.  It is an error to call stmWait
177  * if the thread is already waiting.
178  */
179
180 extern StgBool stmWait(StgTSO *tso, StgTRecHeader *trec);
181
182 /*
183  * Test whether the current transaction context is valid and, if so,
184  * leave the thread waiting and mark it as blocked again.  If the
185  * transaction context is no longer valid then stop the thread waiting
186  * and leave it as unblocked.  It is an error to call stmReWait if the
187  * thread is not waiting.
188  */
189
190 extern StgBool stmReWait(StgTSO *tso);
191
192 /*
193  * Merge the accesses made so far in the second trec into the first trec.
194  * Note that the resulting trec is only intended to be used in wait operations.
195  * This avoids defining what happens if "trec" and "other" contain conflicting
196  * updates.
197  */
198
199 extern StgBool stmMergeForWaiting(StgTRecHeader *trec, StgTRecHeader *other);
200
201
202 /*----------------------------------------------------------------------
203
204    Data access operations
205    ----------------------
206 */
207
208 /*
209  * Return the logical contents of 'tvar' within the context of the
210  * thread's current transaction.
211  */
212
213 extern StgClosure *stmReadTVar(StgTRecHeader *trec, 
214                                StgTVar *tvar);
215
216 /* Update the logical contents of 'tvar' within the context of the
217  * thread's current transaction.
218  */
219
220 extern void stmWriteTVar(StgTRecHeader *trec,
221                          StgTVar *tvar, 
222                          StgClosure *new_value);
223
224 /*----------------------------------------------------------------------*/
225
226 /* NULLs */
227
228 #define END_STM_WAIT_QUEUE ((StgTVarWaitQueue *)(void *)&stg_END_STM_WAIT_QUEUE_closure)
229 #define END_STM_CHUNK_LIST ((StgTRecChunk *)(void *)&stg_END_STM_CHUNK_LIST_closure)
230 #define NO_TREC ((StgTRecHeader *)(void *)&stg_NO_TREC_closure)
231
232 /*----------------------------------------------------------------------*/
233
234 #ifdef __cplusplus
235 }
236 #endif
237
238 #endif /* STM_H */
239