hansaplast
hansaplast

Reputation: 11593

Are static variables volatile?

I have this Rust program:

use std::{thread, time};

static mut c:bool = false;

fn main() {
    unsafe {
        // call some FFI program which sets up signals
        c = false;
        while !c {
            thread::sleep(time::Duration::from_millis(10));
        }
    }
}

I give the pointer to c to some FFI program who sets up signals which change c. How can I go sure the the compiler doesn't eliminate the while loop as it assumes c is never going to change?

C has a volatile keyword which tells the compiler not to optimize in these examples. How can I tell the Rust compiler the same thing?

(I tried to read the LLVM IR code but was not able to figure out how to understand it).

Upvotes: 3

Views: 1206

Answers (1)

starblue
starblue

Reputation: 56812

No, static variables are not volatile.

The proper solution within Rust is to use AtomicBool. The following example (from std::sync::atomic) is quite similar to what you want to do:

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;

fn main() {
    let spinlock = Arc::new(AtomicUsize::new(1));

    let spinlock_clone = spinlock.clone();
    let thread = thread::spawn(move|| {
        spinlock_clone.store(0, Ordering::SeqCst);
    });

    // Wait for the other thread to release the lock
    while spinlock.load(Ordering::SeqCst) != 0 {}

    if let Err(panic) = thread.join() {
        println!("Thread had an error: {:?}", panic);
    }
}

You could do it in this way via some callback from the signal handler into Rust.

There are also unsafe functions std::ptr::read_volatile and std::ptr::write_volatile, which can be used to directly access memory. Normally these should only be used for accessing hardware registers or for implementing safe abstractions.

Upvotes: 2

Related Questions