diff options
| author | bors <bors@rust-lang.org> | 2023-10-24 07:32:09 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-10-24 07:32:09 +0000 |
| commit | a15eb7e7d82fe5db0dc04f66ca4f0bd24e5eb1e3 (patch) | |
| tree | 1352a2613ca779a625f86a91f939972ae1672b80 /src/tools/miri/tests | |
| parent | cc13d045f42e2cf2359bda28f0273e42488b168d (diff) | |
| parent | 900b5ef22e34533eef1cb3ae53588f883e01ed93 (diff) | |
| download | rust-a15eb7e7d82fe5db0dc04f66ca4f0bd24e5eb1e3.tar.gz rust-a15eb7e7d82fe5db0dc04f66ca4f0bd24e5eb1e3.zip | |
Auto merge of #3137 - RalfJung:data-race, r=oli-obk
Detect mixed-size and mixed-atomicity non-synchronized accesses Fixes https://github.com/rust-lang/miri/issues/2303
Diffstat (limited to 'src/tools/miri/tests')
15 files changed, 239 insertions, 65 deletions
diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_read.rs b/src/tools/miri/tests/fail/data_race/mixed_size_read.rs new file mode 100644 index 00000000000..d530ed2f5a4 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/mixed_size_read.rs @@ -0,0 +1,25 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +use std::sync::atomic::{AtomicU16, AtomicU8, Ordering}; +use std::thread; + +fn convert(a: &AtomicU16) -> &[AtomicU8; 2] { + unsafe { std::mem::transmute(a) } +} + +// We can't allow mixed-size accesses; they are not possible in C++ and even +// Intel says you shouldn't do it. +fn main() { + let a = AtomicU16::new(0); + let a16 = &a; + let a8 = convert(a16); + + thread::scope(|s| { + s.spawn(|| { + a16.load(Ordering::SeqCst); + }); + s.spawn(|| { + a8[0].load(Ordering::SeqCst); + //~^ ERROR: Race condition detected between (1) 2-byte Atomic Load on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Load on thread `<unnamed>` + }); + }); +} diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr b/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr new file mode 100644 index 00000000000..06944a11db8 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/mixed_size_read.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Race condition detected between (1) 2-byte Atomic Load on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here + --> $DIR/mixed_size_read.rs:LL:CC + | +LL | a8[0].load(Ordering::SeqCst); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte Atomic Load on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/mixed_size_read.rs:LL:CC + | +LL | a16.load(Ordering::SeqCst); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span): + = note: inside closure at $DIR/mixed_size_read.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_write.rs b/src/tools/miri/tests/fail/data_race/mixed_size_write.rs new file mode 100644 index 00000000000..df3551612c3 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/mixed_size_write.rs @@ -0,0 +1,25 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 -Zmiri-disable-weak-memory-emulation +use std::sync::atomic::{AtomicU16, AtomicU8, Ordering}; +use std::thread; + +fn convert(a: &AtomicU16) -> &[AtomicU8; 2] { + unsafe { std::mem::transmute(a) } +} + +// We can't allow mixed-size accesses; they are not possible in C++ and even +// Intel says you shouldn't do it. +fn main() { + let a = AtomicU16::new(0); + let a16 = &a; + let a8 = convert(a16); + + thread::scope(|s| { + s.spawn(|| { + a16.store(1, Ordering::SeqCst); + }); + s.spawn(|| { + a8[0].store(1, Ordering::SeqCst); + //~^ ERROR: Race condition detected between (1) 2-byte Atomic Store on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Store on thread `<unnamed>` + }); + }); +} diff --git a/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr b/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr new file mode 100644 index 00000000000..4bb949175bf --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/mixed_size_write.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Race condition detected between (1) 2-byte Atomic Store on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here + --> $DIR/mixed_size_write.rs:LL:CC + | +LL | a8[0].store(1, Ordering::SeqCst); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 2-byte Atomic Store on thread `<unnamed>` and (2) 1-byte (different-size) Atomic Store on thread `<unnamed>` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/mixed_size_write.rs:LL:CC + | +LL | a16.store(1, Ordering::SeqCst); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span): + = note: inside closure at $DIR/mixed_size_write.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/data_race/read_read_race1.rs b/src/tools/miri/tests/fail/data_race/read_read_race1.rs new file mode 100644 index 00000000000..eebfbc74d40 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/read_read_race1.rs @@ -0,0 +1,27 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 +use std::sync::atomic::{AtomicU16, Ordering}; +use std::thread; + +// Make sure races between atomic and non-atomic reads are detected. +// This seems harmless but C++ does not allow them, so we can't allow them for now either. +// This test coverse the case where the non-atomic access come first. +fn main() { + let a = AtomicU16::new(0); + + thread::scope(|s| { + s.spawn(|| { + let ptr = &a as *const AtomicU16 as *mut u16; + unsafe { ptr.read() }; + }); + s.spawn(|| { + thread::yield_now(); + + // We also put a non-atomic access here, but that should *not* be reported. + let ptr = &a as *const AtomicU16 as *mut u16; + unsafe { ptr.read() }; + // Then do the atomic access. + a.load(Ordering::SeqCst); + //~^ ERROR: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` + }); + }); +} diff --git a/src/tools/miri/tests/fail/data_race/read_read_race1.stderr b/src/tools/miri/tests/fail/data_race/read_read_race1.stderr new file mode 100644 index 00000000000..158b438bd0d --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/read_read_race1.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here + --> $DIR/read_read_race1.rs:LL:CC + | +LL | a.load(Ordering::SeqCst); + | ^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) Read on thread `<unnamed>` and (2) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/read_read_race1.rs:LL:CC + | +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span): + = note: inside closure at $DIR/read_read_race1.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/data_race/read_read_race2.rs b/src/tools/miri/tests/fail/data_race/read_read_race2.rs new file mode 100644 index 00000000000..230b429e287 --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/read_read_race2.rs @@ -0,0 +1,27 @@ +//@compile-flags: -Zmiri-preemption-rate=0.0 +use std::sync::atomic::{AtomicU16, Ordering}; +use std::thread; + +// Make sure races between atomic and non-atomic reads are detected. +// This seems harmless but C++ does not allow them, so we can't allow them for now either. +// This test coverse the case where the atomic access come first. +fn main() { + let a = AtomicU16::new(0); + + thread::scope(|s| { + s.spawn(|| { + // We also put a non-atomic access here, but that should *not* be reported. + let ptr = &a as *const AtomicU16 as *mut u16; + unsafe { ptr.read() }; + // Then do the atomic access. + a.load(Ordering::SeqCst); + }); + s.spawn(|| { + thread::yield_now(); + + let ptr = &a as *const AtomicU16 as *mut u16; + unsafe { ptr.read() }; + //~^ ERROR: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Read on thread `<unnamed>` + }); + }); +} diff --git a/src/tools/miri/tests/fail/data_race/read_read_race2.stderr b/src/tools/miri/tests/fail/data_race/read_read_race2.stderr new file mode 100644 index 00000000000..7f867b9edbb --- /dev/null +++ b/src/tools/miri/tests/fail/data_race/read_read_race2.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here + --> $DIR/read_read_race2.rs:LL:CC + | +LL | unsafe { ptr.read() }; + | ^^^^^^^^^^ Data race detected between (1) Atomic Load on thread `<unnamed>` and (2) Read on thread `<unnamed>` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/read_read_race2.rs:LL:CC + | +LL | a.load(Ordering::SeqCst); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span): + = note: inside closure at $DIR/read_read_race2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.rs b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.rs index 7bbb7f9fe7c..36dc0d5f3f7 100644 --- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.rs +++ b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.rs @@ -19,7 +19,7 @@ fn split_u32_ptr(dword: *const u32) -> *const [u16; 2] { // Wine's SRWLock implementation does this, which is definitely undefined in C++ memory model // https://github.com/wine-mirror/wine/blob/303f8042f9db508adaca02ef21f8de4992cb9c03/dlls/ntdll/sync.c#L543-L566 -// Though it probably works just fine on x86 +// It probably works just fine on x86, but Intel does document this as "don't do it!" pub fn main() { let x = static_atomic_u32(0); let j1 = spawn(move || { @@ -31,7 +31,7 @@ pub fn main() { let x_split = split_u32_ptr(x_ptr); unsafe { let hi = ptr::addr_of!((*x_split)[0]); - std::intrinsics::atomic_load_relaxed(hi); //~ ERROR: imperfectly overlapping + std::intrinsics::atomic_load_relaxed(hi); //~ ERROR: different-size } }); diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr index dda22ac9ce2..055585ab96f 100644 --- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr +++ b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr @@ -1,11 +1,17 @@ -error: unsupported operation: racy imperfectly overlapping atomic access is not possible in the C++20 memory model, and not supported by Miri's weak memory emulation +error: Undefined Behavior: Race condition detected between (1) 4-byte Atomic Store on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here --> $DIR/racing_mixed_size.rs:LL:CC | LL | std::intrinsics::atomic_load_relaxed(hi); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ racy imperfectly overlapping atomic access is not possible in the C++20 memory model, and not supported by Miri's weak memory emulation + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte Atomic Store on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here | - = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support - = note: BACKTRACE: +help: and (1) occurred earlier here + --> $DIR/racing_mixed_size.rs:LL:CC + | +LL | x.store(1, Relaxed); + | ^^^^^^^^^^^^^^^^^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span): = note: inside closure at $DIR/racing_mixed_size.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.rs b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.rs index 73178980b7e..5cd14540ca3 100644 --- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.rs +++ b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.rs @@ -16,7 +16,7 @@ fn split_u32_ptr(dword: *const u32) -> *const [u16; 2] { // Racing mixed size reads may cause two loads to read-from // the same store but observe different values, which doesn't make -// sense under the formal model so we forbade this. +// sense under the formal model so we forbid this. pub fn main() { let x = static_atomic(0); @@ -29,7 +29,7 @@ pub fn main() { let x_split = split_u32_ptr(x_ptr); unsafe { let hi = x_split as *const u16 as *const AtomicU16; - (*hi).load(Relaxed); //~ ERROR: imperfectly overlapping + (*hi).load(Relaxed); //~ ERROR: different-size } }); diff --git a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr index 59fa5c74102..2eefa0a87b4 100644 --- a/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr +++ b/src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr @@ -1,11 +1,17 @@ -error: unsupported operation: racy imperfectly overlapping atomic access is not possible in the C++20 memory model, and not supported by Miri's weak memory emulation +error: Undefined Behavior: Race condition detected between (1) 4-byte Atomic Load on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here --> $DIR/racing_mixed_size_read.rs:LL:CC | LL | (*hi).load(Relaxed); - | ^^^^^^^^^^^^^^^^^^^ racy imperfectly overlapping atomic access is not possible in the C++20 memory model, and not supported by Miri's weak memory emulation + | ^^^^^^^^^^^^^^^^^^^ Race condition detected between (1) 4-byte Atomic Load on thread `<unnamed>` and (2) 2-byte (different-size) Atomic Load on thread `<unnamed>` at ALLOC. (2) just happened here | - = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support - = note: BACKTRACE: +help: and (1) occurred earlier here + --> $DIR/racing_mixed_size_read.rs:LL:CC + | +LL | x.load(Relaxed); + | ^^^^^^^^^^^^^^^ + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE (of the first span): = note: inside closure at $DIR/racing_mixed_size_read.rs:LL:CC note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs index a456528ec20..648c004c97c 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs @@ -2,7 +2,7 @@ //@compile-flags: -Zmiri-disable-isolation use std::mem::MaybeUninit; -use std::ptr; +use std::ptr::{self, addr_of}; use std::sync::atomic::AtomicI32; use std::sync::atomic::Ordering; use std::thread; @@ -13,7 +13,7 @@ fn wake_nobody() { // Wake 1 waiter. Expect zero waiters woken up, as nobody is waiting. unsafe { - assert_eq!(libc::syscall(libc::SYS_futex, &futex as *const i32, libc::FUTEX_WAKE, 1), 0); + assert_eq!(libc::syscall(libc::SYS_futex, addr_of!(futex), libc::FUTEX_WAKE, 1), 0); } // Same, but without omitting the unused arguments. @@ -21,7 +21,7 @@ fn wake_nobody() { assert_eq!( libc::syscall( libc::SYS_futex, - &futex as *const i32, + addr_of!(futex), libc::FUTEX_WAKE, 1, ptr::null::<libc::timespec>(), @@ -52,7 +52,7 @@ fn wait_wrong_val() { assert_eq!( libc::syscall( libc::SYS_futex, - &futex as *const i32, + addr_of!(futex), libc::FUTEX_WAIT, 456, ptr::null::<libc::timespec>(), @@ -73,7 +73,7 @@ fn wait_timeout() { assert_eq!( libc::syscall( libc::SYS_futex, - &futex as *const i32, + addr_of!(futex), libc::FUTEX_WAIT, 123, &libc::timespec { tv_sec: 0, tv_nsec: 200_000_000 }, @@ -110,7 +110,7 @@ fn wait_absolute_timeout() { assert_eq!( libc::syscall( libc::SYS_futex, - &futex as *const i32, + addr_of!(futex), libc::FUTEX_WAIT_BITSET, 123, &timeout, @@ -136,7 +136,7 @@ fn wait_wake() { assert_eq!( libc::syscall( libc::SYS_futex, - &FUTEX as *const i32, + addr_of!(FUTEX), libc::FUTEX_WAKE, 10, // Wake up at most 10 threads. ), @@ -149,7 +149,7 @@ fn wait_wake() { assert_eq!( libc::syscall( libc::SYS_futex, - &FUTEX as *const i32, + addr_of!(FUTEX), libc::FUTEX_WAIT, 0, ptr::null::<libc::timespec>(), @@ -173,7 +173,7 @@ fn wait_wake_bitset() { assert_eq!( libc::syscall( libc::SYS_futex, - &FUTEX as *const i32, + addr_of!(FUTEX), libc::FUTEX_WAKE_BITSET, 10, // Wake up at most 10 threads. ptr::null::<libc::timespec>(), @@ -188,7 +188,7 @@ fn wait_wake_bitset() { assert_eq!( libc::syscall( libc::SYS_futex, - &FUTEX as *const i32, + addr_of!(FUTEX), libc::FUTEX_WAKE_BITSET, 10, // Wake up at most 10 threads. ptr::null::<libc::timespec>(), @@ -204,7 +204,7 @@ fn wait_wake_bitset() { assert_eq!( libc::syscall( libc::SYS_futex, - &FUTEX as *const i32, + addr_of!(FUTEX), libc::FUTEX_WAIT_BITSET, 0, ptr::null::<libc::timespec>(), @@ -244,7 +244,7 @@ fn concurrent_wait_wake() { unsafe { let ret = libc::syscall( libc::SYS_futex, - &FUTEX as *const AtomicI32, + addr_of!(FUTEX), libc::FUTEX_WAIT, HELD, ptr::null::<libc::timespec>(), @@ -267,7 +267,7 @@ fn concurrent_wait_wake() { FUTEX.store(FREE, Ordering::Relaxed); unsafe { DATA = 1; - libc::syscall(libc::SYS_futex, &FUTEX as *const AtomicI32, libc::FUTEX_WAKE, 1); + libc::syscall(libc::SYS_futex, addr_of!(FUTEX), libc::FUTEX_WAKE, 1); } t.join().unwrap(); diff --git a/src/tools/miri/tests/pass/concurrency/simple.rs b/src/tools/miri/tests/pass/concurrency/simple.rs index 556e0a24769..ec549a998ba 100644 --- a/src/tools/miri/tests/pass/concurrency/simple.rs +++ b/src/tools/miri/tests/pass/concurrency/simple.rs @@ -62,6 +62,23 @@ fn panic_named() { .unwrap_err(); } +// This is not a data race! +fn shared_readonly() { + use std::sync::Arc; + + let x = Arc::new(42i32); + let h = thread::spawn({ + let x = Arc::clone(&x); + move || { + assert_eq!(*x, 42); + } + }); + + assert_eq!(*x, 42); + + h.join().unwrap(); +} + fn main() { create_and_detach(); create_and_join(); @@ -71,6 +88,7 @@ fn main() { create_nested_and_join(); create_move_in(); create_move_out(); + shared_readonly(); panic(); panic_named(); } diff --git a/src/tools/miri/tests/pass/weak_memory/extra_cpp_unsafe.rs b/src/tools/miri/tests/pass/weak_memory/extra_cpp_unsafe.rs deleted file mode 100644 index 48b15191b38..00000000000 --- a/src/tools/miri/tests/pass/weak_memory/extra_cpp_unsafe.rs +++ /dev/null @@ -1,40 +0,0 @@ -//@compile-flags: -Zmiri-ignore-leaks - -// Tests operations not performable through C++'s atomic API -// but doable in unsafe Rust which we think *should* be fine. -// Nonetheless they may be determined as inconsistent with the -// memory model in the future. - -#![feature(atomic_from_mut)] - -use std::sync::atomic::AtomicU32; -use std::sync::atomic::Ordering::*; -use std::thread::spawn; - -fn static_atomic(val: u32) -> &'static AtomicU32 { - let ret = Box::leak(Box::new(AtomicU32::new(val))); - ret -} - -// We allow perfectly overlapping non-atomic and atomic reads to race -fn racing_mixed_atomicity_read() { - let x = static_atomic(0); - x.store(42, Relaxed); - - let j1 = spawn(move || x.load(Relaxed)); - - let j2 = spawn(move || { - let x_ptr = x as *const AtomicU32 as *const u32; - unsafe { x_ptr.read() } - }); - - let r1 = j1.join().unwrap(); - let r2 = j2.join().unwrap(); - - assert_eq!(r1, 42); - assert_eq!(r2, 42); -} - -pub fn main() { - racing_mixed_atomicity_read(); -} |
