summaryrefslogtreecommitdiffstats
path: root/library/std/src/sys/hermit/futex.rs
blob: b64c174b06c6df2ddda458f2742988a1010374b5 (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
use super::abi;
use crate::ptr::null;
use crate::sync::atomic::AtomicU32;
use crate::time::Duration;

pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -> bool {
    // Calculate the timeout as a relative timespec.
    //
    // Overflows are rounded up to an infinite timeout (None).
    let timespec = timeout.and_then(|dur| {
        Some(abi::timespec {
            tv_sec: dur.as_secs().try_into().ok()?,
            tv_nsec: dur.subsec_nanos().into(),
        })
    });

    let r = unsafe {
        abi::futex_wait(
            futex.as_mut_ptr(),
            expected,
            timespec.as_ref().map_or(null(), |t| t as *const abi::timespec),
            abi::FUTEX_RELATIVE_TIMEOUT,
        )
    };

    r != -abi::errno::ETIMEDOUT
}

#[inline]
pub fn futex_wake(futex: &AtomicU32) -> bool {
    unsafe { abi::futex_wake(futex.as_mut_ptr(), 1) > 0 }
}

#[inline]
pub fn futex_wake_all(futex: &AtomicU32) {
    unsafe {
        abi::futex_wake(futex.as_mut_ptr(), i32::MAX);
    }
}