xref: /drstd/src/std/sys/sgx/waitqueue/spin_mutex.rs (revision 86982c5e9b2eaa583327251616ee822c36288824)
1 //! Trivial spinlock-based implementation of `sync::Mutex`.
2 // FIXME: Perhaps use Intel TSX to avoid locking?
3 
4 #[cfg(test)]
5 mod tests;
6 
7 use crate::std::cell::UnsafeCell;
8 use crate::std::hint;
9 use crate::std::ops::{Deref, DerefMut};
10 use crate::std::sync::atomic::{AtomicBool, Ordering};
11 
12 #[derive(Default)]
13 pub struct SpinMutex<T> {
14     value: UnsafeCell<T>,
15     lock: AtomicBool,
16 }
17 
18 unsafe impl<T: Send> Send for SpinMutex<T> {}
19 unsafe impl<T: Send> Sync for SpinMutex<T> {}
20 
21 pub struct SpinMutexGuard<'a, T: 'a> {
22     mutex: &'a SpinMutex<T>,
23 }
24 
25 impl<'a, T> !Send for SpinMutexGuard<'a, T> {}
26 unsafe impl<'a, T: Sync> Sync for SpinMutexGuard<'a, T> {}
27 
28 impl<T> SpinMutex<T> {
29     pub const fn new(value: T) -> Self {
30         SpinMutex {
31             value: UnsafeCell::new(value),
32             lock: AtomicBool::new(false),
33         }
34     }
35 
36     #[inline(always)]
37     pub fn lock(&self) -> SpinMutexGuard<'_, T> {
38         loop {
39             match self.try_lock() {
40                 None => {
41                     while self.lock.load(Ordering::Relaxed) {
42                         hint::spin_loop()
43                     }
44                 }
45                 Some(guard) => return guard,
46             }
47         }
48     }
49 
50     #[inline(always)]
51     pub fn try_lock(&self) -> Option<SpinMutexGuard<'_, T>> {
52         if self
53             .lock
54             .compare_exchange(false, true, Ordering::Acquire, Ordering::Acquire)
55             .is_ok()
56         {
57             Some(SpinMutexGuard { mutex: self })
58         } else {
59             None
60         }
61     }
62 }
63 
64 /// Lock the Mutex or return false.
65 pub macro try_lock_or_false($e:expr) {
66     if let Some(v) = $e.try_lock() {
67         v
68     } else {
69         return false;
70     }
71 }
72 
73 impl<'a, T> Deref for SpinMutexGuard<'a, T> {
74     type Target = T;
75 
76     fn deref(&self) -> &T {
77         unsafe { &*self.mutex.value.get() }
78     }
79 }
80 
81 impl<'a, T> DerefMut for SpinMutexGuard<'a, T> {
82     fn deref_mut(&mut self) -> &mut T {
83         unsafe { &mut *self.mutex.value.get() }
84     }
85 }
86 
87 impl<'a, T> Drop for SpinMutexGuard<'a, T> {
88     fn drop(&mut self) {
89         self.mutex.lock.store(false, Ordering::Release)
90     }
91 }
92