use super::hermit_abi; use crate::ptr::null; use crate::sync::atomic::Atomic; use crate::time::Duration; /// An atomic for use as a futex that is at least 32-bits but may be larger pub type Futex = Atomic; /// Must be the underlying type of Futex pub type Primitive = u32; /// An atomic for use as a futex that is at least 8-bits but may be larger. pub type SmallFutex = Atomic; /// Must be the underlying type of SmallFutex pub type SmallPrimitive = u32; pub fn futex_wait(futex: &Atomic, expected: u32, timeout: Option) -> bool { // Calculate the timeout as a relative timespec. // // Overflows are rounded up to an infinite timeout (None). let timespec = timeout.and_then(|dur| { Some(hermit_abi::timespec { tv_sec: dur.as_secs().try_into().ok()?, tv_nsec: dur.subsec_nanos().try_into().ok()?, }) }); let r = unsafe { hermit_abi::futex_wait( futex.as_ptr(), expected, timespec.as_ref().map_or(null(), |t| t as *const hermit_abi::timespec), hermit_abi::FUTEX_RELATIVE_TIMEOUT, ) }; r != -hermit_abi::errno::ETIMEDOUT } #[inline] pub fn futex_wake(futex: &Atomic) -> bool { unsafe { hermit_abi::futex_wake(futex.as_ptr(), 1) > 0 } } #[inline] pub fn futex_wake_all(futex: &Atomic) { unsafe { hermit_abi::futex_wake(futex.as_ptr(), i32::MAX); } }