1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use fortanix_sgx_abi::Tcs;
13 use super::abi::thread;
15 use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex, NotifiedTcs, try_lock_or_false};
18 inner: SpinMutex<WaitVariable<bool>>,
21 // Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
23 pub const fn new() -> Mutex {
24 Mutex { inner: SpinMutex::new(WaitVariable::new(false)) }
28 pub unsafe fn init(&mut self) {}
31 pub unsafe fn lock(&self) {
32 let mut guard = self.inner.lock();
33 if *guard.lock_var() {
34 // Another thread has the lock, wait
35 WaitQueue::wait(guard)
36 // Another thread has passed the lock to us
38 // We are just now obtaining the lock
39 *guard.lock_var_mut() = true;
44 pub unsafe fn unlock(&self) {
45 let guard = self.inner.lock();
46 if let Err(mut guard) = WaitQueue::notify_one(guard) {
47 // No other waiters, unlock
48 *guard.lock_var_mut() = false;
50 // There was a thread waiting, just pass the lock
55 pub unsafe fn try_lock(&self) -> bool {
56 let mut guard = try_lock_or_false!(self.inner);
57 if *guard.lock_var() {
58 // Another thread has the lock
61 // We are just now obtaining the lock
62 *guard.lock_var_mut() = true;
68 pub unsafe fn destroy(&self) {}
71 struct ReentrantLock {
76 pub struct ReentrantMutex {
77 inner: SpinMutex<WaitVariable<ReentrantLock>>,
81 pub const fn uninitialized() -> ReentrantMutex {
83 inner: SpinMutex::new(WaitVariable::new(ReentrantLock { owner: None, count: 0 }))
88 pub unsafe fn init(&mut self) {}
91 pub unsafe fn lock(&self) {
92 let mut guard = self.inner.lock();
93 match guard.lock_var().owner {
94 Some(tcs) if tcs != thread::current() => {
95 // Another thread has the lock, wait
96 WaitQueue::wait(guard);
97 // Another thread has passed the lock to us
100 // We are just now obtaining the lock
101 guard.lock_var_mut().owner = Some(thread::current());
102 guard.lock_var_mut().count += 1;
108 pub unsafe fn unlock(&self) {
109 let mut guard = self.inner.lock();
110 if guard.lock_var().count > 1 {
111 guard.lock_var_mut().count -= 1;
113 match WaitQueue::notify_one(guard) {
115 // No other waiters, unlock
116 guard.lock_var_mut().count = 0;
117 guard.lock_var_mut().owner = None;
120 // There was a thread waiting, just pass the lock
121 if let NotifiedTcs::Single(tcs) = guard.notified_tcs() {
122 guard.lock_var_mut().owner = Some(tcs)
124 unreachable!() // called notify_one
132 pub unsafe fn try_lock(&self) -> bool {
133 let mut guard = try_lock_or_false!(self.inner);
134 match guard.lock_var().owner {
135 Some(tcs) if tcs != thread::current() => {
136 // Another thread has the lock
140 // We are just now obtaining the lock
141 guard.lock_var_mut().owner = Some(thread::current());
142 guard.lock_var_mut().count += 1;
149 pub unsafe fn destroy(&self) {}