]> git.lizzy.rs Git - rust.git/blob - src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.rs
Rollup merge of #101555 - jhpratt:stabilize-mixed_integer_ops, r=joshtriplett
[rust.git] / src / tools / miri / tests / fail / should-pass / cpp20_rwc_syncs.rs
1 //@compile-flags: -Zmiri-ignore-leaks
2
3 // https://plv.mpi-sws.org/scfix/paper.pdf
4 // 2.2 Second Problem: SC Fences are Too Weak
5 // This test should pass under the C++20 model Rust is using.
6 // Unfortunately, Miri's weak memory emulation only follows the C++11 model
7 // as we don't know how to correctly emulate C++20's revised SC semantics,
8 // so we have to stick to C++11 emulation from existing research.
9
10 use std::sync::atomic::Ordering::*;
11 use std::sync::atomic::{fence, AtomicUsize};
12 use std::thread::spawn;
13
14 // Spins until it reads the given value
15 fn reads_value(loc: &AtomicUsize, val: usize) -> usize {
16     while loc.load(Relaxed) != val {
17         std::hint::spin_loop();
18     }
19     val
20 }
21
22 // We can't create static items because we need to run each test
23 // multiple tests
24 fn static_atomic(val: usize) -> &'static AtomicUsize {
25     let ret = Box::leak(Box::new(AtomicUsize::new(val)));
26     // A workaround to put the initialization value in the store buffer.
27     // See https://github.com/rust-lang/miri/issues/2164
28     ret.load(Relaxed);
29     ret
30 }
31
32 fn test_cpp20_rwc_syncs() {
33     /*
34     int main() {
35         atomic_int x = 0;
36         atomic_int y = 0;
37
38         {{{ x.store(1,mo_relaxed);
39         ||| { r1=x.load(mo_relaxed).readsvalue(1);
40               fence(mo_seq_cst);
41               r2=y.load(mo_relaxed); }
42         ||| { y.store(1,mo_relaxed);
43               fence(mo_seq_cst);
44               r3=x.load(mo_relaxed); }
45         }}}
46         return 0;
47     }
48     */
49     let x = static_atomic(0);
50     let y = static_atomic(0);
51
52     let j1 = spawn(move || {
53         x.store(1, Relaxed);
54     });
55
56     let j2 = spawn(move || {
57         reads_value(&x, 1);
58         fence(SeqCst);
59         y.load(Relaxed)
60     });
61
62     let j3 = spawn(move || {
63         y.store(1, Relaxed);
64         fence(SeqCst);
65         x.load(Relaxed)
66     });
67
68     j1.join().unwrap();
69     let b = j2.join().unwrap();
70     let c = j3.join().unwrap();
71
72     // We cannot write assert_ne!() since ui_test's fail
73     // tests expect exit status 1, whereas panics produce 101.
74     // Our ui_test does not yet support overriding failure status codes.
75     if (b, c) == (0, 0) {
76         // This *should* be unreachable, but Miri will reach it.
77         unsafe {
78             std::hint::unreachable_unchecked(); //~ERROR: unreachable
79         }
80     }
81 }
82
83 pub fn main() {
84     for _ in 0..500 {
85         test_cpp20_rwc_syncs();
86     }
87 }