Skip to content

Commit 24c19b8

Browse files
committed
miri: no longer complain about read-read races
1 parent 704210e commit 24c19b8

File tree

6 files changed

+44
-123
lines changed

6 files changed

+44
-123
lines changed

src/tools/miri/src/concurrency/data_race.rs

+6-17
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ impl MemoryCellClocks {
498498
Ok(())
499499
}
500500

501-
/// Detect data-races with an atomic read, caused by a non-atomic access that does
501+
/// Detect data-races with an atomic read, caused by a non-atomic write that does
502502
/// not happen-before the atomic-read.
503503
fn atomic_read_detect(
504504
&mut self,
@@ -509,12 +509,8 @@ impl MemoryCellClocks {
509509
trace!("Atomic read with vectors: {:#?} :: {:#?}", self, thread_clocks);
510510
let atomic = self.atomic_access(thread_clocks, access_size)?;
511511
atomic.read_vector.set_at_index(&thread_clocks.clock, index);
512-
// Make sure the last non-atomic write and all non-atomic reads were before this access.
513-
if self.write_was_before(&thread_clocks.clock) && self.read <= thread_clocks.clock {
514-
Ok(())
515-
} else {
516-
Err(DataRace)
517-
}
512+
// Make sure the last non-atomic write was before this access.
513+
if self.write_was_before(&thread_clocks.clock) { Ok(()) } else { Err(DataRace) }
518514
}
519515

520516
/// Detect data-races with an atomic write, either with a non-atomic read or with
@@ -551,11 +547,9 @@ impl MemoryCellClocks {
551547
}
552548
thread_clocks.clock.index_mut(index).set_read_type(read_type);
553549
if self.write_was_before(&thread_clocks.clock) {
550+
// We must be ordered-after all atomic writes.
554551
let race_free = if let Some(atomic) = self.atomic() {
555-
// We must be ordered-after all atomic accesses, reads and writes.
556-
// This ensures we don't mix atomic and non-atomic accesses.
557552
atomic.write_vector <= thread_clocks.clock
558-
&& atomic.read_vector <= thread_clocks.clock
559553
} else {
560554
true
561555
};
@@ -955,9 +949,7 @@ impl VClockAlloc {
955949
let mut other_size = None; // if `Some`, this was a size-mismatch race
956950
let write_clock;
957951
let (other_access, other_thread, other_clock) =
958-
// First check the atomic-nonatomic cases. If it looks like multiple
959-
// cases apply, this one should take precedence, else it might look like
960-
// we are reporting races between two non-atomic reads.
952+
// First check the atomic-nonatomic cases.
961953
if !access.is_atomic() &&
962954
let Some(atomic) = mem_clocks.atomic() &&
963955
let Some(idx) = Self::find_gt_index(&atomic.write_vector, &active_clocks.clock)
@@ -1005,10 +997,7 @@ impl VClockAlloc {
1005997
assert!(!involves_non_atomic);
1006998
Some("overlapping unsynchronized atomic accesses must use the same access size")
1007999
} else if access.is_read() && other_access.is_read() {
1008-
assert!(involves_non_atomic);
1009-
Some(
1010-
"overlapping atomic and non-atomic accesses must be synchronized, even if both are read-only",
1011-
)
1000+
panic!("there should be no same-size read-read races")
10121001
} else {
10131002
None
10141003
};

src/tools/miri/tests/fail/data_race/read_read_race1.rs

-30
This file was deleted.

src/tools/miri/tests/fail/data_race/read_read_race1.stderr

-22
This file was deleted.

src/tools/miri/tests/fail/data_race/read_read_race2.rs

-30
This file was deleted.

src/tools/miri/tests/fail/data_race/read_read_race2.stderr

-22
This file was deleted.

src/tools/miri/tests/pass/concurrency/data_race.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//@compile-flags: -Zmiri-disable-weak-memory-emulation -Zmiri-preemption-rate=0
22

3-
use std::sync::atomic::{fence, AtomicUsize, Ordering};
4-
use std::thread::spawn;
3+
use std::sync::atomic::*;
4+
use std::thread::{self, spawn};
55

66
#[derive(Copy, Clone)]
77
struct EvilSend<T>(pub T);
@@ -112,9 +112,45 @@ pub fn test_simple_release() {
112112
}
113113
}
114114

115+
// This test coverse the case where the non-atomic access come first.
116+
fn test_read_read_race1() {
117+
let a = AtomicU16::new(0);
118+
119+
thread::scope(|s| {
120+
s.spawn(|| {
121+
let ptr = &a as *const AtomicU16 as *mut u16;
122+
unsafe { ptr.read() };
123+
});
124+
s.spawn(|| {
125+
thread::yield_now();
126+
127+
a.load(Ordering::SeqCst);
128+
});
129+
});
130+
}
131+
132+
// This test coverse the case where the atomic access come first.
133+
fn test_read_read_race2() {
134+
let a = AtomicU16::new(0);
135+
136+
thread::scope(|s| {
137+
s.spawn(|| {
138+
a.load(Ordering::SeqCst);
139+
});
140+
s.spawn(|| {
141+
thread::yield_now();
142+
143+
let ptr = &a as *const AtomicU16 as *mut u16;
144+
unsafe { ptr.read() };
145+
});
146+
});
147+
}
148+
115149
pub fn main() {
116150
test_fence_sync();
117151
test_multiple_reads();
118152
test_rmw_no_block();
119153
test_simple_release();
154+
test_read_read_race1();
155+
test_read_read_race2();
120156
}

0 commit comments

Comments
 (0)