summaryrefslogtreecommitdiff
path: root/src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs
blob: 5da5497f9829f05773521bc80ffadb7f6753110c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//@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();
}