2022-07-05 04:15:22 -05:00
|
|
|
//@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.
|
2022-05-19 14:14:16 -05:00
|
|
|
// 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,
|
2022-05-19 14:14:16 -05:00
|
|
|
// 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
|
|
|
|
2022-05-19 14:14:16 -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 {
|
2022-05-17 14:04:18 -05:00
|
|
|
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)));
|
2022-05-19 14:14:16 -05:00
|
|
|
// A workaround to put the initialization value in the store buffer.
|
2022-05-29 13:48:36 -05:00
|
|
|
// 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();
|
|
|
|
|
2022-06-05 04:37:40 -05:00
|
|
|
// 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) {
|
2022-06-05 04:37:40 -05:00
|
|
|
// This *should* be unreachable, but Miri will reach it.
|
2022-06-21 01:40:39 -05:00
|
|
|
unsafe {
|
2022-07-24 13:28:45 -05:00
|
|
|
std::hint::unreachable_unchecked(); //~ERROR: unreachable
|
2022-06-21 01:40:39 -05:00
|
|
|
}
|
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
|
|
|
}
|