//@compile-flags: -Zmiri-ignore-leaks // https://plv.mpi-sws.org/scfix/paper.pdf // 2.2 Second Problem: SC Fences are Too Weak // This test should pass under the C++20 model Rust is using. // Unfortunately, Miri's weak memory emulation only follows the C++11 model // as we don't know how to correctly emulate C++20's revised SC semantics, // so we have to stick to C++11 emulation from existing research. use std::sync::atomic::Ordering::*; use std::sync::atomic::{fence, AtomicUsize}; use std::thread::spawn; // Spins until it reads the given value fn reads_value(loc: &AtomicUsize, val: usize) -> usize { while loc.load(Relaxed) != val { std::hint::spin_loop(); } val } // We can't create static items because we need to run each test // multiple tests fn static_atomic(val: usize) -> &'static AtomicUsize { let ret = Box::leak(Box::new(AtomicUsize::new(val))); // A workaround to put the initialization value in the store buffer. // See https://github.com/rust-lang/miri/issues/2164 ret.load(Relaxed); ret } fn test_cpp20_rwc_syncs() { /* int main() { atomic_int x = 0; atomic_int y = 0; {{{ x.store(1,mo_relaxed); ||| { r1=x.load(mo_relaxed).readsvalue(1); fence(mo_seq_cst); r2=y.load(mo_relaxed); } ||| { y.store(1,mo_relaxed); fence(mo_seq_cst); r3=x.load(mo_relaxed); } }}} return 0; } */ let x = static_atomic(0); let y = static_atomic(0); let j1 = spawn(move || { x.store(1, Relaxed); }); let j2 = spawn(move || { reads_value(&x, 1); fence(SeqCst); y.load(Relaxed) }); let j3 = spawn(move || { y.store(1, Relaxed); fence(SeqCst); x.load(Relaxed) }); j1.join().unwrap(); let b = j2.join().unwrap(); let c = j3.join().unwrap(); // We cannot write assert_ne!() since ui_test's fail // tests expect exit status 1, whereas panics produce 101. // Our ui_test does not yet support overriding failure status codes. if (b, c) == (0, 0) { // This *should* be unreachable, but Miri will reach it. unsafe { std::hint::unreachable_unchecked(); //~ERROR: unreachable } } } pub fn main() { for _ in 0..500 { test_cpp20_rwc_syncs(); } }