From 2f69f0e7f16e1ab1582fb427eaeb642a1958e69b Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jeremy@system76.com> Date: Wed, 23 Dec 2020 12:18:17 -0700 Subject: [PATCH] Add simple semaphore implementation using futex --- src/sync/mod.rs | 2 ++ src/sync/semaphore.rs | 46 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/sync/semaphore.rs diff --git a/src/sync/mod.rs b/src/sync/mod.rs index 758365c7..430abd5b 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 00000000..7734c58a --- /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; + } + } + } +} -- GitLab