42 lines
1023 B
Rust
42 lines
1023 B
Rust
//@only-target-windows: Uses win32 api functions
|
|
// We are making scheduler assumptions here.
|
|
//@compile-flags: -Zmiri-preemption-rate=0
|
|
|
|
use std::os::windows::io::IntoRawHandle;
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
use std::thread;
|
|
|
|
extern "system" {
|
|
fn WaitForSingleObject(handle: usize, timeout: u32) -> u32;
|
|
}
|
|
|
|
const INFINITE: u32 = u32::MAX;
|
|
|
|
fn main() {
|
|
static FLAG: AtomicBool = AtomicBool::new(false);
|
|
|
|
let blocker = thread::spawn(|| {
|
|
while !FLAG.load(Ordering::Relaxed) {
|
|
thread::yield_now();
|
|
}
|
|
})
|
|
.into_raw_handle() as usize;
|
|
|
|
let waiter = move || {
|
|
unsafe {
|
|
assert_eq!(WaitForSingleObject(blocker, INFINITE), 0);
|
|
}
|
|
};
|
|
|
|
let waiter1 = thread::spawn(waiter);
|
|
let waiter2 = thread::spawn(waiter);
|
|
|
|
// this yield ensures `waiter1` & `waiter2` are blocked on `blocker` by this point
|
|
thread::yield_now();
|
|
|
|
FLAG.store(true, Ordering::Relaxed);
|
|
|
|
waiter1.join().unwrap();
|
|
waiter2.join().unwrap();
|
|
}
|