| #[cfg(target_arch = "wasm32")] |
| use core::arch::wasm32 as wasm; |
| #[cfg(target_arch = "wasm64")] |
| use core::arch::wasm64 as wasm; |
| |
| 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<Primitive>; |
| /// 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<SmallPrimitive>; |
| /// Must be the underlying type of SmallFutex |
| pub type SmallPrimitive = u32; |
| |
| /// Wait for a futex_wake operation to wake us. |
| /// |
| /// Returns directly if the futex doesn't hold the expected value. |
| /// |
| /// Returns false on timeout, and true in all other cases. |
| pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool { |
| let timeout = timeout.and_then(|t| t.as_nanos().try_into().ok()).unwrap_or(-1); |
| unsafe { |
| wasm::memory_atomic_wait32( |
| futex as *const Atomic<u32> as *mut i32, |
| expected as i32, |
| timeout, |
| ) < 2 |
| } |
| } |
| |
| /// Wakes up one thread that's blocked on `futex_wait` on this futex. |
| /// |
| /// Returns true if this actually woke up such a thread, |
| /// or false if no thread was waiting on this futex. |
| pub fn futex_wake(futex: &Atomic<u32>) -> bool { |
| unsafe { wasm::memory_atomic_notify(futex as *const Atomic<u32> as *mut i32, 1) > 0 } |
| } |
| |
| /// Wakes up all threads that are waiting on `futex_wait` on this futex. |
| pub fn futex_wake_all(futex: &Atomic<u32>) { |
| unsafe { |
| wasm::memory_atomic_notify(futex as *const Atomic<u32> as *mut i32, i32::MAX as u32); |
| } |
| } |