Commit ab3d1f28 authored by tharris's avatar tharris

[project @ 2005-06-06 08:49:07 by tharris]

Remove SMP-only fields from STM data structures from non-SMP builds
parent c34520dc
......@@ -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
......
......@@ -182,6 +182,15 @@ extern StgBool stmWait(StgRegTable *reg,
extern StgBool stmReWait(StgTSO *tso);
/*----------------------------------------------------------------------
TVar management operations
--------------------------
*/
extern StgTVar *stmNewTVar(StgRegTable *reg,
StgClosure *new_value);
/*----------------------------------------------------------------------
Data access operations
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -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;
}
/*......................................................................*/
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment