use core::ops::Deref; use core::sync::atomic::{AtomicU32, Ordering}; use libc::{syscall, SYS_futex}; #[repr(C)] pub struct Futex(AtomicU32); pub type Atomic = AtomicU32; pub type Primitive = u32; pub type SmallFutex = Futex; pub type SmallAtomic = Atomic; pub type SmallPrimitive = Primitive; impl Futex { #[inline] pub const fn new(initial_value: u32) -> Self { Self(AtomicU32::new(initial_value)) } #[inline] pub fn wait(&self, expected_start_value: u32) { unsafe { syscall( SYS_futex, core::ptr::from_ref(&self.0), libc::FUTEX_WAIT_BITSET | libc::FUTEX_PRIVATE_FLAG, expected_start_value, core::ptr::null::<()>(), core::ptr::null::(), // This argument is unused for FUTEX_WAIT_BITSET. !0u32, // A full bitmask, to make it behave like a regular FUTEX_WAIT. ); } } #[inline] pub fn wake(&self) -> bool { let ptr = &self.0 as *const AtomicU32; const OP: libc::c_int = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG; unsafe { libc::syscall(libc::SYS_futex, ptr, OP, 1) > 0 } } #[inline] pub fn wake_all(&self) { let ptr = &raw const self.0; let op = libc::FUTEX_WAKE | libc::FUTEX_PRIVATE_FLAG; unsafe { syscall(libc::SYS_futex, ptr, op, i32::MAX); } } } impl Deref for Futex { type Target = Atomic; #[inline] fn deref(&self) -> &Self::Target { &self.0 } }