about summary refs log tree commit diff
path: root/library/std/src/sys/sgx/waitqueue/spin_mutex.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/sgx/waitqueue/spin_mutex.rs')
-rw-r--r--library/std/src/sys/sgx/waitqueue/spin_mutex.rs76
1 files changed, 76 insertions, 0 deletions
diff --git a/library/std/src/sys/sgx/waitqueue/spin_mutex.rs b/library/std/src/sys/sgx/waitqueue/spin_mutex.rs
new file mode 100644
index 00000000000..d99ce895da5
--- /dev/null
+++ b/library/std/src/sys/sgx/waitqueue/spin_mutex.rs
@@ -0,0 +1,76 @@
+#[cfg(test)]
+mod tests;
+
+use crate::cell::UnsafeCell;
+use crate::ops::{Deref, DerefMut};
+use crate::sync::atomic::{spin_loop_hint, AtomicBool, Ordering};
+
+#[derive(Default)]
+pub struct SpinMutex<T> {
+    value: UnsafeCell<T>,
+    lock: AtomicBool,
+}
+
+unsafe impl<T: Send> Send for SpinMutex<T> {}
+unsafe impl<T: Send> Sync for SpinMutex<T> {}
+
+pub struct SpinMutexGuard<'a, T: 'a> {
+    mutex: &'a SpinMutex<T>,
+}
+
+impl<'a, T> !Send for SpinMutexGuard<'a, T> {}
+unsafe impl<'a, T: Sync> Sync for SpinMutexGuard<'a, T> {}
+
+impl<T> SpinMutex<T> {
+    pub const fn new(value: T) -> Self {
+        SpinMutex { value: UnsafeCell::new(value), lock: AtomicBool::new(false) }
+    }
+
+    #[inline(always)]
+    pub fn lock(&self) -> SpinMutexGuard<'_, T> {
+        loop {
+            match self.try_lock() {
+                None => {
+                    while self.lock.load(Ordering::Relaxed) {
+                        spin_loop_hint()
+                    }
+                }
+                Some(guard) => return guard,
+            }
+        }
+    }
+
+    #[inline(always)]
+    pub fn try_lock(&self) -> Option<SpinMutexGuard<'_, T>> {
+        if !self.lock.compare_and_swap(false, true, Ordering::Acquire) {
+            Some(SpinMutexGuard { mutex: self })
+        } else {
+            None
+        }
+    }
+}
+
+/// Lock the Mutex or return false.
+pub macro try_lock_or_false($e:expr) {
+    if let Some(v) = $e.try_lock() { v } else { return false }
+}
+
+impl<'a, T> Deref for SpinMutexGuard<'a, T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe { &*self.mutex.value.get() }
+    }
+}
+
+impl<'a, T> DerefMut for SpinMutexGuard<'a, T> {
+    fn deref_mut(&mut self) -> &mut T {
+        unsafe { &mut *self.mutex.value.get() }
+    }
+}
+
+impl<'a, T> Drop for SpinMutexGuard<'a, T> {
+    fn drop(&mut self) {
+        self.mutex.lock.store(false, Ordering::Release)
+    }
+}