diff --git a/sync/Cargo.toml b/sync/Cargo.toml index d30ae44..9827725 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -18,4 +18,4 @@ doctest = false [dependencies] mc-sgx-panic = { path = "../panic", version = "=0.1.0" } -mc-sgx-tstdc = { version = "=0.4.1-beta.0", git = "https://github.com/mobilecoinfoundation/sgx", rev = "957abb01ea215ff2e56b372867ac304a69a0614e" } +mc-sgx-tstdc = { version = "=0.4.1-beta.0", git = "https://github.com/mobilecoinfoundation/sgx", rev = "a9d62a9608f6a908eac16955e8cdb7537a5a7b9a" } diff --git a/sync/src/sys/locks/condvar.rs b/sync/src/sys/locks/condvar.rs new file mode 100644 index 0000000..7d09f28 --- /dev/null +++ b/sync/src/sys/locks/condvar.rs @@ -0,0 +1,67 @@ +// Copyright (c) 2023 The MobileCoin Foundation + +//! Rust condition variable implementation used in SGX environments +#![allow(dead_code)] +use crate::sys::locks::Mutex; +use mc_sgx_tstdc::Condvar as SgxCondvar; + +/// The condition variable backend to use with the common Rust std lib Condvar +/// interface +pub(crate) struct Condvar { + inner: SgxCondvar, +} + +unsafe impl Send for Condvar {} +unsafe impl Sync for Condvar {} + +impl Condvar { + pub const fn new() -> Self { + Self { + inner: SgxCondvar::new(), + } + } + + /// Wait on the condition variable + /// + /// # Arguments + /// * `mutex` - The mutex to paired with the current [`Condvar`] + /// + /// # Panics + /// If: + /// - the condition variable got into an invalid state + /// - the [`Mutex`] is not locked by the current thread + pub fn wait(&self, mutex: &Mutex) { + self.inner + .wait(mutex.raw()) + .expect("Condition variable is invalid or mutex is not locked by current thread"); + } + + /// Notify the next waiting thread (if any) of the condition variable event + /// + /// Returns when there are no waiting threads. + /// + /// # Panics + /// If the condition variable got into an invalid state + pub fn notify_one(&self) { + self.inner + .notify_one() + .expect("Condition variable is in an invalid state"); + } + + /// Notify *all* waiting threads of the condition variable event + /// + /// Returns when there are no waiting threads. + /// + /// # Panics + /// If: + /// - the condition variable got into an invalid state + /// - ran out of memory while notifying other threads. + pub fn notify_all(&self) { + // For the `expect()` message, out of memory could be a reason for + // failing, but it is unlikely given that the memory allocation is a + // `void *` per waiting thread. + self.inner + .notify_all() + .expect("Condition variable is in an invalid state"); + } +} diff --git a/sync/src/sys/locks/mod.rs b/sync/src/sys/locks/mod.rs index 39dc689..66aeaf5 100644 --- a/sync/src/sys/locks/mod.rs +++ b/sync/src/sys/locks/mod.rs @@ -2,5 +2,7 @@ //! Platform specific concurrency locking primitives. +mod condvar; mod mutex; + pub(crate) use mutex::Mutex; diff --git a/sync/src/sys/locks/mutex.rs b/sync/src/sys/locks/mutex.rs index cf35547..0c53d00 100644 --- a/sync/src/sys/locks/mutex.rs +++ b/sync/src/sys/locks/mutex.rs @@ -54,4 +54,8 @@ impl Mutex { .try_lock() .expect("Mutex got into an invalid state.") } + + pub(crate) fn raw(&self) -> &SgxMutex { + &self.inner + } }