1 use fortanix_sgx_abi::Tcs;
3 use super::abi::thread;
5 use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex, NotifiedTcs, try_lock_or_false};
8 inner: SpinMutex<WaitVariable<bool>>,
11 // Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
13 pub const fn new() -> Mutex {
14 Mutex { inner: SpinMutex::new(WaitVariable::new(false)) }
18 pub unsafe fn init(&mut self) {}
21 pub unsafe fn lock(&self) {
22 let mut guard = self.inner.lock();
23 if *guard.lock_var() {
24 // Another thread has the lock, wait
25 WaitQueue::wait(guard)
26 // Another thread has passed the lock to us
28 // We are just now obtaining the lock
29 *guard.lock_var_mut() = true;
34 pub unsafe fn unlock(&self) {
35 let guard = self.inner.lock();
36 if let Err(mut guard) = WaitQueue::notify_one(guard) {
37 // No other waiters, unlock
38 *guard.lock_var_mut() = false;
40 // There was a thread waiting, just pass the lock
45 pub unsafe fn try_lock(&self) -> bool {
46 let mut guard = try_lock_or_false!(self.inner);
47 if *guard.lock_var() {
48 // Another thread has the lock
51 // We are just now obtaining the lock
52 *guard.lock_var_mut() = true;
58 pub unsafe fn destroy(&self) {}
61 struct ReentrantLock {
66 pub struct ReentrantMutex {
67 inner: SpinMutex<WaitVariable<ReentrantLock>>,
71 pub const fn uninitialized() -> ReentrantMutex {
73 inner: SpinMutex::new(WaitVariable::new(ReentrantLock { owner: None, count: 0 }))
78 pub unsafe fn init(&mut self) {}
81 pub unsafe fn lock(&self) {
82 let mut guard = self.inner.lock();
83 match guard.lock_var().owner {
84 Some(tcs) if tcs != thread::current() => {
85 // Another thread has the lock, wait
86 WaitQueue::wait(guard);
87 // Another thread has passed the lock to us
90 // We are just now obtaining the lock
91 guard.lock_var_mut().owner = Some(thread::current());
92 guard.lock_var_mut().count += 1;
98 pub unsafe fn unlock(&self) {
99 let mut guard = self.inner.lock();
100 if guard.lock_var().count > 1 {
101 guard.lock_var_mut().count -= 1;
103 match WaitQueue::notify_one(guard) {
105 // No other waiters, unlock
106 guard.lock_var_mut().count = 0;
107 guard.lock_var_mut().owner = None;
110 // There was a thread waiting, just pass the lock
111 if let NotifiedTcs::Single(tcs) = guard.notified_tcs() {
112 guard.lock_var_mut().owner = Some(tcs)
114 unreachable!() // called notify_one
122 pub unsafe fn try_lock(&self) -> bool {
123 let mut guard = try_lock_or_false!(self.inner);
124 match guard.lock_var().owner {
125 Some(tcs) if tcs != thread::current() => {
126 // Another thread has the lock
130 // We are just now obtaining the lock
131 guard.lock_var_mut().owner = Some(thread::current());
132 guard.lock_var_mut().count += 1;
139 pub unsafe fn destroy(&self) {}