diff --git a/src/sync/waitval.rs b/src/sync/waitval.rs index 8f83ce5e3b..f6ba84f1ac 100644 --- a/src/sync/waitval.rs +++ b/src/sync/waitval.rs @@ -1,14 +1,13 @@ -// Semaphores need one post per wait, Once doesn't have separate post and wait, and while mutexes -// wait for releasing the lock, it calls notify_one and needs locking again to access the value. - use core::cell::UnsafeCell; use core::mem::MaybeUninit; -use core::sync::atomic::Ordering; +use core::sync::atomic::{AtomicU32 as AtomicUint, Ordering}; use super::*; +/// An unsafe "one thread to one thread" synchronization primitive. Used for and modeled after +/// pthread_join only, at the moment. pub struct Waitval { - state: AtomicLock, + state: AtomicUint, value: UnsafeCell>, } @@ -18,20 +17,22 @@ unsafe impl Sync for Waitval {} impl Waitval { pub const fn new() -> Self { Self { - state: AtomicLock::new(0), + state: AtomicUint::new(0), value: UnsafeCell::new(MaybeUninit::uninit()), } } + // SAFETY: Caller must ensure both (1) that the value has not yet been initialized, and (2) + // that this is never run by more than one thread simultaneously. pub unsafe fn post(&self, value: T) { self.value.get().write(MaybeUninit::new(value)); self.state.store(1, Ordering::Release); - self.state.notify_all(); + crate::sync::futex_wake(&self.state, i32::MAX); } pub fn wait(&self) -> &T { while self.state.load(Ordering::Acquire) == 0 { - self.state.wait_if(0, None); + crate::sync::futex_wait(&self.state, 0, None); } unsafe { (*self.value.get()).assume_init_ref() }