From f0d48100334c99d300f393a4c2c89a721a6b6cc6 Mon Sep 17 00:00:00 2001 From: Nick Santana Date: Tue, 24 Jan 2023 11:09:15 -0800 Subject: [PATCH] Add `mc-sgx-sync::sys::locks::Condvar` Add the backend end `Condvar` implementation for use in SGX enclaves --- sync/src/sys/locks.rs | 2 ++ sync/src/sys/locks/condvar.rs | 67 +++++++++++++++++++++++++++++++++++ sync/src/sys/locks/mutex.rs | 4 +++ 3 files changed, 73 insertions(+) create mode 100644 sync/src/sys/locks/condvar.rs diff --git a/sync/src/sys/locks.rs b/sync/src/sys/locks.rs index 39dc689..66aeaf5 100644 --- a/sync/src/sys/locks.rs +++ b/sync/src/sys/locks.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/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/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 + } }