diff options
Diffstat (limited to 'src/futex/linux.rs')
| -rwxr-xr-x | src/futex/linux.rs | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/src/futex/linux.rs b/src/futex/linux.rs new file mode 100755 index 0000000..80ca5a6 --- /dev/null +++ b/src/futex/linux.rs @@ -0,0 +1,61 @@ +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::<u32>(), // 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 + } +} |
