Reputation: 11593
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
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