Closed
Description
The following code should be fine, but Miri raises an error:
use std::sync::atomic::Ordering::*;
use std::sync::atomic::*;
static P: AtomicPtr<u8> = AtomicPtr::new(core::ptr::null_mut());
fn main() {
// Create the local variable, and initialize it.
let mut val: u8 = 0;
let t1 = std::thread::spawn(|| {
while P.load(Relaxed).is_null() {
std::hint::spin_loop();
}
unsafe {
// Initialize `*P`.
let ptr = P.load(Relaxed);
*ptr = 127;
}
});
// Actually generate memory for the local variable.
// This is the time its value is actually written to memory:
// that's *after* the thread above was spawned!
P.store(std::ptr::addr_of_mut!(val), Relaxed);
// Wait for the thread to be done.
t1.join().unwrap();
// Read initialized value.
assert_eq!(val, 127);
}
The issue has been described well by CAD97 here:
Without having dived into Miri, it likely is a false positive due to places not being allocated into memory until their reference is taken. It's an optimization for most cases (there's a lot of bookkeeping happening for allocations in Miri) but results in a false positive here. Assuming that's a correct assessment, the fix would be to assign a timestamp corresponding to the local place initialization when reifying into an allocation, instead of the timestamp of the reification itself.