Skip to content

Commit d1c8e93

Browse files
authored
Merge pull request rust-lang#4796 from RalfJung/data-race-ice
fix ICE for particular data race situations
2 parents e7e90dc + a6c2e50 commit d1c8e93

File tree

4 files changed

+69
-3
lines changed

4 files changed

+69
-3
lines changed

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,7 @@ impl VClockAlloc {
11161116
{
11171117
(AccessType::AtomicStore, idx, &atomic.write_vector)
11181118
} else if !access.is_atomic() &&
1119+
!access.is_read() &&
11191120
let Some(atomic) = mem_clocks.atomic() &&
11201121
let Some(idx) = Self::find_gt_index(&atomic.read_vector, &active_clocks.clock)
11211122
{
@@ -1124,7 +1125,7 @@ impl VClockAlloc {
11241125
} else if mem_clocks.write.1 > active_clocks.clock[mem_clocks.write.0] {
11251126
write_clock = mem_clocks.write();
11261127
(AccessType::NaWrite(mem_clocks.write_type), mem_clocks.write.0, &write_clock)
1127-
} else if let Some(idx) = Self::find_gt_index(&mem_clocks.read, &active_clocks.clock) {
1128+
} else if !access.is_read() && let Some(idx) = Self::find_gt_index(&mem_clocks.read, &active_clocks.clock) {
11281129
(AccessType::NaRead(mem_clocks.read[idx].read_type()), idx, &mem_clocks.read)
11291130
// Finally, mixed-size races.
11301131
} else if access.is_atomic() && let Some(atomic) = mem_clocks.atomic() && atomic.size != Some(access_size) {
@@ -1157,7 +1158,9 @@ impl VClockAlloc {
11571158
assert!(!involves_non_atomic);
11581159
Some("overlapping unsynchronized atomic accesses must use the same access size")
11591160
} else if access.is_read() && other_access.is_read() {
1160-
panic!("there should be no same-size read-read races")
1161+
panic!(
1162+
"there should be no same-size read-read races\naccess: {access:?}\nother_access: {other_access:?}"
1163+
)
11611164
} else {
11621165
None
11631166
};

src/tools/miri/src/concurrency/vector_clock.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,24 @@ const SMALL_VECTOR: usize = 4;
4848
/// The time-stamps recorded in the data-race detector consist of both
4949
/// a 32-bit unsigned integer which is the actual timestamp, and a `Span`
5050
/// so that diagnostics can report what code was responsible for an operation.
51-
#[derive(Clone, Copy, Debug)]
51+
#[derive(Clone, Copy)]
5252
pub(super) struct VTimestamp {
5353
/// The lowest bit indicates read type, the rest is the time.
5454
/// `1` indicates a retag read, `0` a regular read.
5555
time_and_read_type: u32,
5656
pub span: Span,
5757
}
5858

59+
impl Debug for VTimestamp {
60+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61+
f.debug_struct("VTimestamp")
62+
.field("time", &self.time())
63+
.field("read_type", &self.read_type())
64+
.field("span", &self.span)
65+
.finish()
66+
}
67+
}
68+
5969
impl VTimestamp {
6070
pub const ZERO: VTimestamp = VTimestamp::new(0, NaReadType::Read, DUMMY_SP);
6171

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//@compile-flags: -Zmiri-deterministic-concurrency
2+
// A case that is not covered by `mixed_size_read_write`.
3+
#![feature(ptr_as_ref_unchecked)]
4+
5+
use std::sync::atomic::*;
6+
use std::thread;
7+
8+
fn main() {
9+
let data = AtomicI32::new(0);
10+
11+
thread::scope(|s| {
12+
s.spawn(|| unsafe {
13+
let _val = (&raw const data).read();
14+
let _val = (&raw const data).cast::<AtomicI8>().as_ref_unchecked().compare_exchange(
15+
0,
16+
1,
17+
Ordering::Relaxed,
18+
Ordering::Relaxed,
19+
);
20+
thread::yield_now();
21+
unreachable!();
22+
});
23+
s.spawn(|| {
24+
let _val = data.load(Ordering::Relaxed); //~ERROR: /Race condition detected between \(1\) 1-byte atomic store .* and \(2\) 4-byte atomic load/
25+
});
26+
});
27+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: Undefined Behavior: Race condition detected between (1) 1-byte atomic store on thread `unnamed-ID` and (2) 4-byte atomic load on thread `unnamed-ID` at ALLOC
2+
--> tests/fail/data_race/mixed_size_read_write_read.rs:LL:CC
3+
|
4+
LL | ... let _val = data.load(Ordering::Relaxed);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ (2) just happened here
6+
|
7+
help: and (1) occurred earlier here
8+
--> tests/fail/data_race/mixed_size_read_write_read.rs:LL:CC
9+
|
10+
LL | let _val = (&raw const data).cast::<AtomicI8>().as_ref_unchecked().compare_exchange(
11+
| ________________________^
12+
LL | | 0,
13+
LL | | 1,
14+
LL | | Ordering::Relaxed,
15+
LL | | Ordering::Relaxed,
16+
LL | | );
17+
| |_____________^
18+
= help: overlapping unsynchronized atomic accesses must use the same access size
19+
= help: see https://doc.rust-lang.org/nightly/std/sync/atomic/index.html#memory-model-for-atomic-accesses for more information about the Rust memory model
20+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
21+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
22+
23+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
24+
25+
error: aborting due to 1 previous error
26+

0 commit comments

Comments
 (0)