]> git.proxmox.com Git - rustc.git/blob - src/libstd/sys/sgx/mutex.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / libstd / sys / sgx / mutex.rs
1 use fortanix_sgx_abi::Tcs;
2
3 use super::abi::thread;
4
5 use super::waitqueue::{try_lock_or_false, NotifiedTcs, SpinMutex, WaitQueue, WaitVariable};
6
7 pub struct Mutex {
8 inner: SpinMutex<WaitVariable<bool>>,
9 }
10
11 // Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
12 impl Mutex {
13 pub const fn new() -> Mutex {
14 Mutex { inner: SpinMutex::new(WaitVariable::new(false)) }
15 }
16
17 #[inline]
18 pub unsafe fn init(&mut self) {}
19
20 #[inline]
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
27 } else {
28 // We are just now obtaining the lock
29 *guard.lock_var_mut() = true;
30 }
31 }
32
33 #[inline]
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;
39 } else {
40 // There was a thread waiting, just pass the lock
41 }
42 }
43
44 #[inline]
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
49 false
50 } else {
51 // We are just now obtaining the lock
52 *guard.lock_var_mut() = true;
53 true
54 }
55 }
56
57 #[inline]
58 pub unsafe fn destroy(&self) {}
59 }
60
61 struct ReentrantLock {
62 owner: Option<Tcs>,
63 count: usize,
64 }
65
66 pub struct ReentrantMutex {
67 inner: SpinMutex<WaitVariable<ReentrantLock>>,
68 }
69
70 impl ReentrantMutex {
71 pub const fn uninitialized() -> ReentrantMutex {
72 ReentrantMutex {
73 inner: SpinMutex::new(WaitVariable::new(ReentrantLock { owner: None, count: 0 })),
74 }
75 }
76
77 #[inline]
78 pub unsafe fn init(&self) {}
79
80 #[inline]
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
88 }
89 _ => {
90 // We are just now obtaining the lock
91 guard.lock_var_mut().owner = Some(thread::current());
92 guard.lock_var_mut().count += 1;
93 }
94 }
95 }
96
97 #[inline]
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;
102 } else {
103 match WaitQueue::notify_one(guard) {
104 Err(mut guard) => {
105 // No other waiters, unlock
106 guard.lock_var_mut().count = 0;
107 guard.lock_var_mut().owner = None;
108 }
109 Ok(mut guard) => {
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)
113 } else {
114 unreachable!() // called notify_one
115 }
116 }
117 }
118 }
119 }
120
121 #[inline]
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
127 false
128 }
129 _ => {
130 // We are just now obtaining the lock
131 guard.lock_var_mut().owner = Some(thread::current());
132 guard.lock_var_mut().count += 1;
133 true
134 }
135 }
136 }
137
138 #[inline]
139 pub unsafe fn destroy(&self) {}
140 }