rust/tests/fail/should-pass/cpp20_rwc_syncs.rs

88 lines
2.3 KiB
Rust
Raw Normal View History

//@compile-flags: -Zmiri-ignore-leaks
2022-05-07 11:34:18 -05:00
// 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
2022-05-07 11:34:18 -05:00
// 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.
2022-05-07 11:34:18 -05:00
use std::sync::atomic::Ordering::*;
use std::sync::atomic::{fence, AtomicUsize};
2022-05-25 14:46:08 -05:00
use std::thread::spawn;
2022-05-07 11:34:18 -05:00
// Spins until it reads the given value
2022-05-07 11:34:18 -05:00
fn reads_value(loc: &AtomicUsize, val: usize) -> usize {
while loc.load(Relaxed) != val {
std::hint::spin_loop();
2022-05-07 11:34:18 -05:00
}
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
2022-05-25 14:46:08 -05:00
ret.load(Relaxed);
2022-05-07 11:34:18 -05:00
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.
2022-05-07 11:34:18 -05:00
if (b, c) == (0, 0) {
// This *should* be unreachable, but Miri will reach it.
unsafe {
2022-07-24 13:28:45 -05:00
std::hint::unreachable_unchecked(); //~ERROR: unreachable
}
2022-05-07 11:34:18 -05:00
}
}
pub fn main() {
for _ in 0..500 {
test_cpp20_rwc_syncs();
}
2022-05-25 14:46:08 -05:00
}