You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rollup merge of #128778 - RalfJung:atomic-read-read-races, r=Mark-Simulacrum
atomics: allow atomic and non-atomic reads to race
We currently define our atomics in terms of C++ `atomic_ref`. That has the unfortunate side-effect of making it UB for an atomic and a non-atomic read to race (concretely, [this code](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d1a743774e60923db33def7fe314d754) has UB). There's really no good reason for this, all the academic models of the C++ memory model I am aware of allow this -- C++ just disallows this because of their insistence on an "object model" with typed memory, where `atomic_ref` temporarily creates an "atomic object" that may not be accesses via regular non-atomic operations.
So instead of tying our operations to `atomic_ref`, let us tie them directly to the underlying C++ memory model. I am not sure what is the best way to phrase this, so here's a first attempt.
We also carve out an exception from the "no mixed-size atomic accesses" rule to permit mixed-size atomic reads -- given that we permit mixed-size non-atomic reads, it seems odd that this would be disallowed for atomic reads. However, when an atomic write races with any other atomic operation, they must use the same size.
With this change, it is finally the case that every non-atomic access can be replaced by an atomic access without introducing UB.
Cc `@rust-lang/opsem` `@chorman0773` `@m-ou-se` `@WaffleLapkin` `@Amanieu`
Fixesrust-lang/unsafe-code-guidelines#483
error: Undefined Behavior: Race condition detected between (1) multiple differently-sized atomic loads, including one load on thread `unnamed-ID` and (2) 2-byte atomic store on thread `unnamed-ID` at ALLOC. (2) just happened here
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) multiple differently-sized atomic loads, including one load on thread `unnamed-ID` and (2) 2-byte atomic store on thread `unnamed-ID` at ALLOC. (2) just happened here
= help: overlapping unsynchronized atomic accesses must use the same access size
13
+
= 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
14
+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
15
+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
16
+
= note: BACKTRACE (of the first span) on thread `unnamed-ID`:
17
+
= note: inside closure at tests/fail/data_race/mixed_size_read_read_write.rs:LL:CC
18
+
19
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: Undefined Behavior: Race condition detected between (1) multiple differently-sized atomic loads, including one load on thread `unnamed-ID` and (2) 1-byte atomic store on thread `unnamed-ID` at ALLOC. (2) just happened here
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) multiple differently-sized atomic loads, including one load on thread `unnamed-ID` and (2) 1-byte atomic store on thread `unnamed-ID` at ALLOC. (2) just happened here
= help: overlapping unsynchronized atomic accesses must use the same access size
13
+
= 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
14
+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
15
+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
16
+
= note: BACKTRACE (of the first span) on thread `unnamed-ID`:
17
+
= note: inside closure at tests/fail/data_race/mixed_size_read_read_write.rs:LL:CC
18
+
19
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
// Two variants: the atomic store matches the size of the first or second atomic load.
5
+
//@revisions: match_first_load match_second_load
6
+
7
+
use std::sync::atomic::{AtomicU16,AtomicU8,Ordering};
8
+
use std::thread;
9
+
10
+
fnconvert(a:&AtomicU16) -> &[AtomicU8;2]{
11
+
unsafe{ std::mem::transmute(a)}
12
+
}
13
+
14
+
// We can't allow mixed-size accesses; they are not possible in C++ and even
15
+
// Intel says you shouldn't do it.
16
+
fnmain(){
17
+
let a = AtomicU16::new(0);
18
+
let a16 = &a;
19
+
let a8 = convert(a16);
20
+
21
+
thread::scope(|s| {
22
+
s.spawn(|| {
23
+
a16.load(Ordering::SeqCst);
24
+
});
25
+
s.spawn(|| {
26
+
a8[0].load(Ordering::SeqCst);
27
+
});
28
+
s.spawn(|| {
29
+
thread::yield_now();// make sure this happens last
30
+
ifcfg!(match_first_load){
31
+
a16.store(0,Ordering::SeqCst);
32
+
//~[match_first_load]^ ERROR: Race condition detected between (1) multiple differently-sized atomic loads, including one load on thread `unnamed-1` and (2) 2-byte atomic store on thread `unnamed-3`
33
+
}else{
34
+
a8[0].store(0,Ordering::SeqCst);
35
+
//~[match_second_load]^ ERROR: Race condition detected between (1) multiple differently-sized atomic loads, including one load on thread `unnamed-1` and (2) 1-byte atomic store on thread `unnamed-3`
error: Undefined Behavior: Race condition detected between (1) 1-byte atomic load on thread `unnamed-ID` and (2) 2-byte atomic store on thread `unnamed-ID` at ALLOC. (2) just happened here
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 1-byte atomic load on thread `unnamed-ID` and (2) 2-byte atomic store on thread `unnamed-ID` at ALLOC. (2) just happened here
= help: overlapping unsynchronized atomic accesses must use the same access size
13
+
= 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
14
+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
15
+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
16
+
= note: BACKTRACE (of the first span) on thread `unnamed-ID`:
17
+
= note: inside closure at tests/fail/data_race/mixed_size_read_write.rs:LL:CC
18
+
19
+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
Copy file name to clipboardExpand all lines: tests/fail/data_race/mixed_size_read_write.write_read.stderr
+7-7Lines changed: 7 additions & 7 deletions
Original file line number
Diff line number
Diff line change
@@ -1,20 +1,20 @@
1
-
error: Undefined Behavior: Race condition detected between (1) 2-byte atomic load on thread `unnamed-ID` and (2) 1-byte atomic load on thread `unnamed-ID` at ALLOC. (2) just happened here
2
-
--> tests/fail/data_race/mixed_size_read.rs:LL:CC
1
+
error: Undefined Behavior: Race condition detected between (1) 2-byte atomic store on thread `unnamed-ID` and (2) 1-byte atomic load on thread `unnamed-ID` at ALLOC. (2) just happened here
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte atomic load on thread `unnamed-ID` and (2) 1-byte atomic load on thread `unnamed-ID` at ALLOC. (2) just happened here
5
+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte atomic store on thread `unnamed-ID` and (2) 1-byte atomic load on thread `unnamed-ID` at ALLOC. (2) just happened here
= help: overlapping unsynchronized atomic accesses must use the same access size
13
13
= 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
14
14
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
15
15
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
16
16
= note: BACKTRACE (of the first span) on thread `unnamed-ID`:
17
-
= note: inside closure at tests/fail/data_race/mixed_size_read.rs:LL:CC
17
+
= note: inside closure at tests/fail/data_race/mixed_size_read_write.rs:LL:CC
18
18
19
19
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
0 commit comments