about summary refs log tree commit diff
path: root/src/tools/miri/tests
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-10-24 07:32:09 +0000
committerbors <bors@rust-lang.org>2023-10-24 07:32:09 +0000
commita15eb7e7d82fe5db0dc04f66ca4f0bd24e5eb1e3 (patch)
tree1352a2613ca779a625f86a91f939972ae1672b80 /src/tools/miri/tests
parentcc13d045f42e2cf2359bda28f0273e42488b168d (diff)
parent900b5ef22e34533eef1cb3ae53588f883e01ed93 (diff)
downloadrust-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')
-rw-r--r--src/tools/miri/tests/fail/data_race/mixed_size_read.rs25
-rw-r--r--src/tools/miri/tests/fail/data_race/mixed_size_read.stderr20
-rw-r--r--src/tools/miri/tests/fail/data_race/mixed_size_write.rs25
-rw-r--r--src/tools/miri/tests/fail/data_race/mixed_size_write.stderr20
-rw-r--r--src/tools/miri/tests/fail/data_race/read_read_race1.rs27
-rw-r--r--src/tools/miri/tests/fail/data_race/read_read_race1.stderr20
-rw-r--r--src/tools/miri/tests/fail/data_race/read_read_race2.rs27
-rw-r--r--src/tools/miri/tests/fail/data_race/read_read_race2.stderr20
-rw-r--r--src/tools/miri/tests/fail/weak_memory/racing_mixed_size.rs4
-rw-r--r--src/tools/miri/tests/fail/weak_memory/racing_mixed_size.stderr14
-rw-r--r--src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.rs4
-rw-r--r--src/tools/miri/tests/fail/weak_memory/racing_mixed_size_read.stderr14
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs26
-rw-r--r--src/tools/miri/tests/pass/concurrency/simple.rs18
-rw-r--r--src/tools/miri/tests/pass/weak_memory/extra_cpp_unsafe.rs40
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();
-}