diff --git a/src/sync/mod.rs b/src/sync/mod.rs index 758365c7014f7c82e48179fdb529892814b08629..430abd5b783e341adeced608ac5d7f3c004077cc 100644 --- a/src/sync/mod.rs +++ b/src/sync/mod.rs @@ -1,9 +1,11 @@ pub mod mutex; pub mod once; +pub mod semaphore; pub use self::{ mutex::{Mutex, MutexGuard}, once::Once, + semaphore::Semaphore, }; use crate::platform::{types::*, Pal, Sys}; diff --git a/src/sync/semaphore.rs b/src/sync/semaphore.rs new file mode 100644 index 0000000000000000000000000000000000000000..7734c58a171bb0c8c8afecb94e30f792f8b189b3 --- /dev/null +++ b/src/sync/semaphore.rs @@ -0,0 +1,46 @@ +// From https://www.remlab.net/op/futex-misc.shtml +//TODO: improve implementation + +use crate::platform::{types::*, Pal, Sys}; +use super::AtomicLock; +use core::sync::atomic::Ordering; + +pub struct Semaphore { + lock: AtomicLock, +} + +impl Semaphore { + pub const fn new(value: c_int) -> Self { + Self { + lock: AtomicLock::new(value), + } + } + + pub fn post(&self) { + self.lock.fetch_add(1, Ordering::Relaxed); + self.lock.notify_one(); + } + + pub fn wait(&self) { + let mut value = 1; + + loop { + match self.lock.compare_exchange_weak( + value, + value - 1, + Ordering::Acquire, + Ordering::Relaxed + ) { + Ok(ok) => return, + Err(err) => { + value = err; + } + } + + if value == 0 { + self.lock.wait_if(0); + value = 1; + } + } + } +}