-
Notifications
You must be signed in to change notification settings - Fork 392
Description
use std::sync::atomic::Ordering::*;
use std::sync::atomic::{AtomicBool, AtomicUsize};
use std::thread::spawn;
pub fn main() {
// Give these 'static lifetime to avoid using Arc
static X: AtomicUsize = AtomicUsize::new(0);
static T1_DONE: AtomicBool = AtomicBool::new(false);
let t1 = spawn(move || {
X.store(1, Relaxed);
T1_DONE.store(true, Relaxed);
});
let t2 = spawn(move || {
while !T1_DONE.load(Relaxed) {}
X.load(Relaxed)
});
t1.join().unwrap();
let r = t2.join().unwrap();
println!("{r}");
}
On platforms with weaker memory models (such as ARM), it should be possible for the above program to print 0, because X.store(1, Relaxed)
does not happen before X.load(Relaxed)
so it's allowed to observe an "outdated" value.
However, on Miri, once X.store(1, Relaxed)
is executed, the initialisation value 0 can never be observed again. This is because the store buffers used to keep the atomic stores are lazily allocated on the first atomic access of a location. We can't obtain the value in the underlying location in the atomic write shim because calling read_scalar()
on the location has side effects which implies that a read on the location happened in the MIR even though there isn't one.
To fix, rustc_const_eval
needs to provide a method letting us obtain the value on a location for internal machine implementation rather than user program behaviour