1 use fortanix_sgx_abi
::Tcs
;
3 use super::abi
::thread
;
5 use super::waitqueue
::{try_lock_or_false, NotifiedTcs, SpinMutex, WaitQueue, WaitVariable}
;
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(&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) {}