Skip to content
Snippets Groups Projects
Verified Commit beac2482 authored by Jacob Lorentzon's avatar Jacob Lorentzon
Browse files

Use futex directly in waitval.

parent 4faa3155
No related branches found
No related tags found
1 merge request!380Replace pthreads-emb with a native implementation
// 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<T> {
state: AtomicLock,
state: AtomicUint,
value: UnsafeCell<MaybeUninit<T>>,
}
......@@ -18,20 +17,22 @@ unsafe impl<T: Send + Sync> Sync for Waitval<T> {}
impl<T> Waitval<T> {
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() }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment