Skip to content

Initialisation value of atomic types can no longer be observed if the first atomic access is a store #2164

@cbeuw

Description

@cbeuw
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

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-weak-memoryArea: emulation of weak memory effects (store buffers)C-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions