Skip to content

Commit

Permalink
Track read types
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Mar 17, 2024
1 parent 491874c commit 6dac9f6
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 23 deletions.
16 changes: 9 additions & 7 deletions src/concurrency/data_race.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,6 @@ enum AtomicAccessType {
/// of the data-race detector.
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum NaReadType {
/// The read type is unknown.
Unknown,

/// Standard unsynchronized write.
Read,

Expand All @@ -221,7 +218,6 @@ impl NaReadType {
match self {
NaReadType::Read => "non-atomic read",
NaReadType::ImmutableMemory => "shared reference invariant",
NaReadType::Unknown => "some potential non-atomic read access",
}
}
}
Expand Down Expand Up @@ -544,12 +540,14 @@ impl MemoryCellClocks {
&mut self,
thread_clocks: &mut ThreadClockSet,
index: VectorIdx,
read_type: NaReadType,
current_span: Span,
) -> Result<(), DataRace> {
trace!("Unsynchronized read with vectors: {:#?} :: {:#?}", self, thread_clocks);
if !current_span.is_dummy() {
thread_clocks.clock[index].span = current_span;
}
thread_clocks.clock[index].read_type = read_type;
if self.write_was_before(&thread_clocks.clock) {
let race_free = if let Some(atomic) = self.atomic() {
// We must be ordered-after all atomic accesses, reads and writes.
Expand All @@ -560,7 +558,11 @@ impl MemoryCellClocks {
true
};
self.read.set_at_index(&thread_clocks.clock, index);
if race_free { Ok(()) } else { Err(DataRace) }
if race_free {
Ok(())
} else {
Err(DataRace)
}
} else {
Err(DataRace)
}
Expand Down Expand Up @@ -951,7 +953,7 @@ impl VClockAlloc {
write_clock = mem_clocks.write();
(AccessType::NaWrite(mem_clocks.write_type), mem_clocks.write.0, &write_clock)
} else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, &current_clocks.clock) {
(AccessType::NaRead(NaReadType::Unknown), idx, &mem_clocks.read)
(AccessType::NaRead(mem_clocks.read[idx].read_type()), idx, &mem_clocks.read)
// Finally, mixed-size races.
} else if access.is_atomic() && let Some(atomic) = mem_clocks.atomic() && atomic.size != access_size {
// This is only a race if we are not synchronized with all atomic accesses, so find
Expand Down Expand Up @@ -1029,7 +1031,7 @@ impl VClockAlloc {
alloc_ranges.iter_mut(access_range.start, access_range.size)
{
if let Err(DataRace) =
mem_clocks.read_race_detect(&mut thread_clocks, index, current_span)
mem_clocks.read_race_detect(&mut thread_clocks, index, read_type, current_span)
{
drop(thread_clocks);
// Report data-race.
Expand Down
48 changes: 32 additions & 16 deletions src/concurrency/vector_clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use std::{
ops::{Index, IndexMut},
};

use super::data_race::NaReadType;

/// A vector clock index, this is associated with a thread id
/// but in some cases one vector index may be shared with
/// multiple thread ids if it's safe to do so.
Expand Down Expand Up @@ -52,14 +54,20 @@ const SMALL_VECTOR: usize = 4;
pub struct VTimestamp {
time: u32,
pub span: Span,
pub read_type: NaReadType,
}

impl VTimestamp {
pub const ZERO: VTimestamp = VTimestamp { time: 0, span: DUMMY_SP };
pub const ZERO: VTimestamp =
VTimestamp { time: 0, span: DUMMY_SP, read_type: NaReadType::Read };

pub fn span_data(&self) -> SpanData {
self.span.data()
}

pub fn read_type(&self) -> NaReadType {
self.read_type
}
}

impl PartialEq for VTimestamp {
Expand Down Expand Up @@ -212,14 +220,16 @@ impl PartialOrd for VClock {
for (l, r) in iter {
match order {
Ordering::Equal => order = l.cmp(r),
Ordering::Less =>
Ordering::Less => {
if l > r {
return None;
},
Ordering::Greater =>
}
}
Ordering::Greater => {
if l < r {
return None;
},
}
}
}
}

Expand All @@ -234,18 +244,16 @@ impl PartialOrd for VClock {
Ordering::Equal => Some(order),
// Right has at least 1 element > than the implicit 0,
// so the only valid values are Ordering::Less or None.
Ordering::Less =>
match order {
Ordering::Less | Ordering::Equal => Some(Ordering::Less),
Ordering::Greater => None,
},
Ordering::Less => match order {
Ordering::Less | Ordering::Equal => Some(Ordering::Less),
Ordering::Greater => None,
},
// Left has at least 1 element > than the implicit 0,
// so the only valid values are Ordering::Greater or None.
Ordering::Greater =>
match order {
Ordering::Greater | Ordering::Equal => Some(Ordering::Greater),
Ordering::Less => None,
},
Ordering::Greater => match order {
Ordering::Greater | Ordering::Equal => Some(Ordering::Greater),
Ordering::Less => None,
},
}
}

Expand Down Expand Up @@ -380,6 +388,8 @@ impl IndexMut<VectorIdx> for VClock {
#[cfg(test)]
mod tests {

use crate::concurrency::data_race::NaReadType;

use super::{VClock, VTimestamp, VectorIdx};
use rustc_span::DUMMY_SP;
use std::cmp::Ordering;
Expand Down Expand Up @@ -448,7 +458,13 @@ mod tests {
while let Some(0) = slice.last() {
slice = &slice[..slice.len() - 1]
}
VClock(slice.iter().copied().map(|time| VTimestamp { time, span: DUMMY_SP }).collect())
VClock(
slice
.iter()
.copied()
.map(|time| VTimestamp { time, span: DUMMY_SP, read_type: NaReadType::Read })
.collect(),
)
}

fn assert_order(l: &[u32], r: &[u32], o: Option<Ordering>) {
Expand Down

0 comments on commit 6dac9f6

Please sign in to comment.