Skip to content

Commit

Permalink
[wip] weak memory logging
Browse files Browse the repository at this point in the history
  • Loading branch information
cbeuw authored and Andy Wang committed Jun 25, 2022
1 parent 3b4402c commit 64d738c
Showing 1 changed file with 23 additions and 12 deletions.
35 changes: 23 additions & 12 deletions src/concurrency/weak_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ pub(super) struct StoreBuffer {
buffer: VecDeque<StoreElement>,
}

#[derive(PartialEq, Eq)]
enum Recency {
Latest,
Outdated,
}

#[derive(Debug, Clone, PartialEq, Eq)]
struct StoreElement {
/// The identifier of the vector index, corresponding to a thread
Expand Down Expand Up @@ -250,11 +256,11 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
is_seqcst: bool,
rng: &mut (impl rand::Rng + ?Sized),
validate: impl FnOnce() -> InterpResult<'tcx>,
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
) -> InterpResult<'tcx, (ScalarMaybeUninit<Tag>, Recency)> {
// Having a live borrow to store_buffer while calling validate_atomic_load is fine
// because the race detector doesn't touch store_buffer

let store_elem = {
let (store_elem, recency) = {
// The `clocks` we got here must be dropped before calling validate_atomic_load
// as the race detector will update it
let (.., clocks) = global.current_thread_state();
Expand All @@ -270,7 +276,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {

let (index, clocks) = global.current_thread_state();
let loaded = store_elem.load_impl(index, &clocks);
Ok(loaded)
Ok((loaded, recency))
}

fn buffered_write(
Expand All @@ -291,7 +297,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
is_seqcst: bool,
clocks: &ThreadClockSet,
rng: &mut R,
) -> &StoreElement {
) -> (&StoreElement, Recency) {
use rand::seq::IteratorRandom;
let mut found_sc = false;
// FIXME: we want an inclusive take_while (stops after a false predicate, but
Expand All @@ -311,32 +317,27 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
keep_searching = if store_elem.timestamp <= clocks.clock[store_elem.store_index] {
// CoWR: if a store happens-before the current load,
// then we can't read-from anything earlier in modification order.
log::info!("Stopping due to coherent write-read");
false
} else if store_elem.loads.borrow().iter().any(|(&load_index, &load_timestamp)| {
load_timestamp <= clocks.clock[load_index]
}) {
// CoRR: if there was a load from this store which happened-before the current load,
// then we cannot read-from anything earlier in modification order.
log::info!("Stopping due to coherent read-read");
false
} else if store_elem.timestamp <= clocks.fence_seqcst[store_elem.store_index] {
// The current load, which may be sequenced-after an SC fence, can only read-from
// the last store sequenced-before an SC fence in another thread (or any stores
// later than that SC fence)
log::info!("Stopping due to coherent load sequenced after sc fence");
false
} else if store_elem.timestamp <= clocks.write_seqcst[store_elem.store_index]
&& store_elem.is_seqcst
{
// The current non-SC load can only read-from the latest SC store (or any stores later than that
// SC store)
log::info!("Stopping due to needing to load from the last SC store");
false
} else if is_seqcst && store_elem.timestamp <= clocks.read_seqcst[store_elem.store_index] {
// The current SC load can only read-from the last store sequenced-before
// the last SC fence (or any stores later than the SC fence)
log::info!("Stopping due to sc load needing to load from the last SC store before an SC fence");
false
} else {true};

Expand All @@ -354,9 +355,15 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
}
});

candidates
let chosen = candidates
.choose(rng)
.expect("store buffer cannot be empty, an element is populated on construction")
.expect("store buffer cannot be empty, an element is populated on construction");

if std::ptr::eq(chosen, self.buffer.back().expect("store buffer cannot be empty")) {
(chosen, Recency::Latest)
} else {
(chosen, Recency::Outdated)
}
}

/// ATOMIC STORE IMPL in the paper (except we don't need the location's vector clock)
Expand Down Expand Up @@ -484,13 +491,17 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
alloc_range(base_offset, place.layout.size),
latest_in_mo,
)?;
let loaded = buffer.buffered_read(
let (loaded, recency) = buffer.buffered_read(
global,
atomic == AtomicReadOp::SeqCst,
&mut *rng,
validate,
)?;

if recency == Recency::Outdated {
log::trace!("outdated value {:?} read at {:?}", loaded, this.cur_span().data());
}

return Ok(loaded);
}
}
Expand Down

0 comments on commit 64d738c

Please sign in to comment.