From ab3d1f285cef784138d99e70f7359ea6e67f6c25 Mon Sep 17 00:00:00 2001 From: tharris Date: Mon, 6 Jun 2005 08:49:07 +0000 Subject: [PATCH] [project @ 2005-06-06 08:49:07 by tharris] Remove SMP-only fields from STM data structures from non-SMP builds --- ghc/includes/Closures.h | 4 ++ ghc/includes/STM.h | 9 ++++ ghc/includes/mkDerivedConstants.c | 5 -- ghc/rts/GC.c | 6 +++ ghc/rts/GCCompact.c | 2 + ghc/rts/PrimOps.cmm | 17 ++----- ghc/rts/STM.c | 98 ++++++++++++++++++++++++++----------- 7 files changed, 94 insertions(+), 47 deletions(-) diff --git a/ghc/includes/Closures.h b/ghc/includes/Closures.h index c8071fd..506592f 100644 --- a/ghc/includes/Closures.h +++ b/ghc/includes/Closures.h @@ -357,7 +357,9 @@ typedef struct { StgHeader header; StgClosure *volatile current_value; StgTVarWaitQueue *volatile first_wait_queue_entry; +#if defined(SMP) struct StgTRecHeader_ *volatile last_update_by; +#endif } StgTVar; /* new_value == expected_value for read-only accesses */ @@ -366,7 +368,9 @@ typedef struct { StgTVar *tvar; StgClosure *expected_value; StgClosure *new_value; +#if defined(SMP) struct StgTRecHeader_ *saw_update_by; +#endif } TRecEntry; #define TREC_CHUNK_NUM_ENTRIES 256 diff --git a/ghc/includes/STM.h b/ghc/includes/STM.h index cf821dc..0db5185 100644 --- a/ghc/includes/STM.h +++ b/ghc/includes/STM.h @@ -184,6 +184,15 @@ extern StgBool stmReWait(StgTSO *tso); /*---------------------------------------------------------------------- + TVar management operations + -------------------------- +*/ + +extern StgTVar *stmNewTVar(StgRegTable *reg, + StgClosure *new_value); + +/*---------------------------------------------------------------------- + Data access operations ---------------------- */ diff --git a/ghc/includes/mkDerivedConstants.c b/ghc/includes/mkDerivedConstants.c index 4602869..754189c 100644 --- a/ghc/includes/mkDerivedConstants.c +++ b/ghc/includes/mkDerivedConstants.c @@ -374,11 +374,6 @@ main(int argc, char *argv[]) closure_field(StgMVar,tail); closure_field(StgMVar,value); - closure_size(StgTVar); - closure_field(StgTVar,current_value); - closure_field(StgTVar,first_wait_queue_entry); - closure_field(StgTVar,last_update_by); - closure_size(StgBCO); closure_field(StgBCO, instrs); closure_field(StgBCO, literals); diff --git a/ghc/rts/GC.c b/ghc/rts/GC.c index db00d81..f75468f 100644 --- a/ghc/rts/GC.c +++ b/ghc/rts/GC.c @@ -2871,7 +2871,9 @@ scavenge(step *stp) evac_gen = 0; tvar->current_value = evacuate((StgClosure*)tvar->current_value); tvar->first_wait_queue_entry = (StgTVarWaitQueue *)evacuate((StgClosure*)tvar->first_wait_queue_entry); +#if defined(SMP) tvar->last_update_by = (StgTRecHeader *)evacuate((StgClosure*)tvar->last_update_by); +#endif evac_gen = saved_evac_gen; failed_to_evac = rtsTrue; // mutable p += sizeofW(StgTVar); @@ -3217,7 +3219,9 @@ linear_scan: evac_gen = 0; tvar->current_value = evacuate((StgClosure*)tvar->current_value); tvar->first_wait_queue_entry = (StgTVarWaitQueue *)evacuate((StgClosure*)tvar->first_wait_queue_entry); +#if defined(SMP) tvar->last_update_by = (StgTRecHeader *)evacuate((StgClosure*)tvar->last_update_by); +#endif evac_gen = saved_evac_gen; failed_to_evac = rtsTrue; // mutable break; @@ -3530,7 +3534,9 @@ scavenge_one(StgPtr p) evac_gen = 0; tvar->current_value = evacuate((StgClosure*)tvar->current_value); tvar->first_wait_queue_entry = (StgTVarWaitQueue *)evacuate((StgClosure*)tvar->first_wait_queue_entry); +#if defined(SMP) tvar->last_update_by = (StgTRecHeader *)evacuate((StgClosure*)tvar->last_update_by); +#endif evac_gen = saved_evac_gen; failed_to_evac = rtsTrue; // mutable break; diff --git a/ghc/rts/GCCompact.c b/ghc/rts/GCCompact.c index 012235e..f4e66b6 100644 --- a/ghc/rts/GCCompact.c +++ b/ghc/rts/GCCompact.c @@ -675,7 +675,9 @@ thread_obj (StgInfoTable *info, StgPtr p) StgTVar *tvar = (StgTVar *)p; thread((StgPtr)&tvar->current_value); thread((StgPtr)&tvar->first_wait_queue_entry); +#if defined(SMP) thread((StgPtr)&tvar->last_update_by); +#endif return p + sizeofW(StgTVar); } diff --git a/ghc/rts/PrimOps.cmm b/ghc/rts/PrimOps.cmm index 082cb01..7b1c8aa 100644 --- a/ghc/rts/PrimOps.cmm +++ b/ghc/rts/PrimOps.cmm @@ -1330,22 +1330,13 @@ retry_pop_stack: newTVarzh_fast { W_ tv; - W_ trec; + W_ new_value; /* Args: R1 = initialisation value */ - ALLOC_PRIM( SIZEOF_StgTVar, R1_PTR, newTVarzh_fast); - tv = Hp - SIZEOF_StgTVar + WDS(1); - SET_HDR(tv,stg_TVAR_info,W_[CCCS]); - StgTVar_current_value(tv) = R1; - StgTVar_first_wait_queue_entry(tv) = stg_END_STM_WAIT_QUEUE_closure; -#if defined(SMP) - trec = StgTSO_trec(CurrentTSO); - StgTVar_last_update_by(tv) = trec; -#else - StgTVar_last_update_by(tv) = NO_TREC; -#endif - + MAYBE_GC (R1_PTR, newTVarzh_fast); + new_value = R1; + tv = foreign "C" stmNewTVar(BaseReg "ptr", new_value "ptr"); RET_P(tv); } diff --git a/ghc/rts/STM.c b/ghc/rts/STM.c index 2be5c69..74894ec 100644 --- a/ghc/rts/STM.c +++ b/ghc/rts/STM.c @@ -169,7 +169,13 @@ static int shake(void) { /*......................................................................*/ +#define IF_STM_UNIPROC(__X) do { } while (0) +#define IF_STM_CG_LOCK(__X) do { } while (0) +#define IF_STM_FG_LOCKS(__X) do { } while (0) + #if defined(STM_UNIPROC) +#undef IF_STM_UNIPROC +#define IF_STM_UNIPROC(__X) do { __X } while (0) static const StgBool use_read_phase = FALSE; static void lock_stm(StgTRecHeader *trec STG_UNUSED) { @@ -204,13 +210,15 @@ static StgBool cond_lock_tvar(StgTRecHeader *trec STG_UNUSED, StgClosure *result; TRACE("%p : cond_lock_tvar(%p, %p)\n", trec, s, expected); result = s -> current_value; - TRACE("%p : %d\n", (result == expected) ? "success" : "failure"); + TRACE("%p : %s\n", trec, (result == expected) ? "success" : "failure"); return (result == expected); } #endif #if defined(STM_CG_LOCK) /*........................................*/ +#undef IF_STM_CG_LOCK +#define IF_STM_CG_LOCK(__X) do { __X } while (0) static const StgBool use_read_phase = FALSE; static volatile StgTRecHeader *smp_locked = NULL; @@ -259,6 +267,8 @@ static StgBool cond_lock_tvar(StgTRecHeader *trec STG_UNUSED, #if defined(STM_FG_LOCKS) /*...................................*/ +#undef IF_STM_FG_LOCKS +#define IF_STM_FG_LOCKS(__X) do { __X } while (0) static const StgBool use_read_phase = TRUE; static void lock_stm(StgTRecHeader *trec STG_UNUSED) { @@ -381,6 +391,19 @@ static StgTRecHeader *new_stg_trec_header(StgRegTable *reg, return result; } +static StgTVar *new_tvar(StgRegTable *reg, + StgClosure *new_value) { + StgTVar *result; + result = (StgTVar *)allocateLocal(reg, sizeofW(StgTVar)); + SET_HDR (result, &stg_TVAR_info, CCS_SYSTEM); + result -> current_value = new_value; + result -> first_wait_queue_entry = END_STM_WAIT_QUEUE; +#if defined(SMP) + result -> last_update_by = NO_TREC; +#endif + return result; +} + /*......................................................................*/ // Helper functions for managing waiting lists @@ -597,20 +620,23 @@ static StgBool validate_and_acquire_ownership (StgTRecHeader *trec, BREAK_FOR_EACH; } } else { - TRACE("%p : will need to check %p\n", trec, s); - if (s -> current_value != e -> expected_value) { - TRACE("%p : doesn't match\n", trec); - result = FALSE; - BREAK_FOR_EACH; - } - e -> saw_update_by = s -> last_update_by; - if (s -> current_value != e -> expected_value) { - TRACE("%p : doesn't match (race)\n", trec); - result = FALSE; - BREAK_FOR_EACH; - } else { - TRACE("%p : need to check update by %p\n", trec, e -> saw_update_by); - } + ASSERT(use_read_phase); + IF_STM_FG_LOCKS({ + TRACE("%p : will need to check %p\n", trec, s); + if (s -> current_value != e -> expected_value) { + TRACE("%p : doesn't match\n", trec); + result = FALSE; + BREAK_FOR_EACH; + } + e -> saw_update_by = s -> last_update_by; + if (s -> current_value != e -> expected_value) { + TRACE("%p : doesn't match (race)\n", trec); + result = FALSE; + BREAK_FOR_EACH; + } else { + TRACE("%p : need to check update by %p\n", trec, e -> saw_update_by); + } + }); } }); } @@ -633,21 +659,24 @@ static StgBool validate_and_acquire_ownership (StgTRecHeader *trec, // Keir Fraser's PhD dissertation "Practical lock-free programming" discuss // this kind of algorithm. -static StgBool check_read_only(StgTRecHeader *trec) { +static StgBool check_read_only(StgTRecHeader *trec STG_UNUSED) { StgBool result = TRUE; - FOR_EACH_ENTRY(trec, e, { - StgTVar *s; - s = e -> tvar; - if (entry_is_read_only(e)) { - TRACE("%p : check_read_only for TVar %p, saw %p\n", trec, s, e -> saw_update_by); - if (s -> last_update_by != e -> saw_update_by) { - // ||s -> current_value != e -> expected_value) { - TRACE("%p : mismatch\n", trec); - result = FALSE; - BREAK_FOR_EACH; + ASSERT (use_read_phase); + IF_STM_FG_LOCKS({ + FOR_EACH_ENTRY(trec, e, { + StgTVar *s; + s = e -> tvar; + if (entry_is_read_only(e)) { + TRACE("%p : check_read_only for TVar %p, saw %p\n", trec, s, e -> saw_update_by); + if (s -> last_update_by != e -> saw_update_by) { + // ||s -> current_value != e -> expected_value) { + TRACE("%p : mismatch\n", trec); + result = FALSE; + BREAK_FOR_EACH; + } } - } + }); }); return result; @@ -781,6 +810,7 @@ StgBool stmCommitTransaction(StgRegTable *reg STG_UNUSED, StgTRecHeader *trec) { if (use_read_phase) { TRACE("%p : doing read check\n", trec); result = check_read_only(trec); + TRACE("%p : read-check %s\n", trec, result ? "succeeded" : "failed"); } if (result) { @@ -788,7 +818,6 @@ StgBool stmCommitTransaction(StgRegTable *reg STG_UNUSED, StgTRecHeader *trec) { // at the end of the call to validate_and_acquire_ownership. This forms the // linearization point of the commit. - TRACE("%p : read-check succeeded\n", trec); FOR_EACH_ENTRY(trec, e, { StgTVar *s; s = e -> tvar; @@ -799,7 +828,9 @@ StgBool stmCommitTransaction(StgRegTable *reg STG_UNUSED, StgTRecHeader *trec) { ACQ_ASSERT(tvar_is_locked(s, trec)); TRACE("%p : writing %p to %p, waking waiters\n", trec, e -> new_value, s); unpark_waiters_on(s); - s -> last_update_by = trec; + IF_STM_FG_LOCKS({ + s -> last_update_by = trec; + }); unlock_tvar(trec, s, e -> new_value, TRUE); } ACQ_ASSERT(!tvar_is_locked(s, trec)); @@ -1060,3 +1091,12 @@ void stmWriteTVar(StgRegTable *reg, /*......................................................................*/ +StgTVar *stmNewTVar(StgRegTable *reg, + StgClosure *new_value) { + StgTVar *result; + result = new_tvar(reg, new_value); + return result; +} + +/*......................................................................*/ + -- 1.7.10.4