]> git.lizzy.rs Git - rust.git/blob - library/std/src/sys/sgx/mutex.rs
Rollup merge of #105655 - RedDocMD:bug-105645, r=oli-obk
[rust.git] / library / std / src / sys / sgx / mutex.rs
1 use super::waitqueue::{try_lock_or_false, SpinMutex, WaitQueue, WaitVariable};
2 use crate::sys_common::lazy_box::{LazyBox, LazyInit};
3
4 /// FIXME: `UnsafeList` is not movable.
5 struct AllocatedMutex(SpinMutex<WaitVariable<bool>>);
6
7 pub struct Mutex {
8     inner: LazyBox<AllocatedMutex>,
9 }
10
11 impl LazyInit for AllocatedMutex {
12     fn init() -> Box<Self> {
13         Box::new(AllocatedMutex(SpinMutex::new(WaitVariable::new(false))))
14     }
15 }
16
17 // Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
18 impl Mutex {
19     pub const fn new() -> Mutex {
20         Mutex { inner: LazyBox::new() }
21     }
22
23     #[inline]
24     pub fn lock(&self) {
25         let mut guard = self.inner.0.lock();
26         if *guard.lock_var() {
27             // Another thread has the lock, wait
28             WaitQueue::wait(guard, || {})
29         // Another thread has passed the lock to us
30         } else {
31             // We are just now obtaining the lock
32             *guard.lock_var_mut() = true;
33         }
34     }
35
36     #[inline]
37     pub unsafe fn unlock(&self) {
38         let guard = self.inner.0.lock();
39         if let Err(mut guard) = WaitQueue::notify_one(guard) {
40             // No other waiters, unlock
41             *guard.lock_var_mut() = false;
42         } else {
43             // There was a thread waiting, just pass the lock
44         }
45     }
46
47     #[inline]
48     pub fn try_lock(&self) -> bool {
49         let mut guard = try_lock_or_false!(self.inner.0);
50         if *guard.lock_var() {
51             // Another thread has the lock
52             false
53         } else {
54             // We are just now obtaining the lock
55             *guard.lock_var_mut() = true;
56             true
57         }
58     }
59 }