X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=includes%2FSTM.h;fp=includes%2FSTM.h;h=4c2b109f73ab33923ced896c9a47fe1335656238;hb=0065d5ab628975892cea1ec7303f968c3338cbe1;hp=0000000000000000000000000000000000000000;hpb=28a464a75e14cece5db40f2765a29348273ff2d2;p=ghc-hetmet.git diff --git a/includes/STM.h b/includes/STM.h new file mode 100644 index 0000000..4c2b109 --- /dev/null +++ b/includes/STM.h @@ -0,0 +1,237 @@ +/*---------------------------------------------------------------------- + * + * (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 +); + +/* + * Exit the current transaction context, abandoning any read/write + * operations performed within it and removing the thread from any + * tvar wait queues if it was waitin. Note that if nested transactions + * are not fully supported then this may leave the enclosing + * transaction contexts doomed to abort. + */ + +extern void stmAbortTransaction(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. +*/ + +/* + * 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_WAIT_QUEUE ((StgTVarWaitQueue *)(void *)&stg_END_STM_WAIT_QUEUE_closure) +#define END_STM_CHUNK_LIST ((StgTRecChunk *)(void *)&stg_END_STM_CHUNK_LIST_closure) + +#if IN_STG_CODE +#define NO_TREC (stg_NO_TREC_closure) +#else +#define NO_TREC ((StgTRecHeader *)(void *)&stg_NO_TREC_closure) +#endif + +/*----------------------------------------------------------------------*/ + +#ifdef __cplusplus +} +#endif + +#endif /* STM_H */ +