1 use super::waitqueue::{try_lock_or_false, SpinMutex, WaitQueue, WaitVariable};
2 use crate::sys_common::lazy_box::{LazyBox, LazyInit};
4 /// FIXME: `UnsafeList` is not movable.
5 struct AllocatedMutex(SpinMutex<WaitVariable<bool>>);
8 inner: LazyBox<AllocatedMutex>,
11 impl LazyInit for AllocatedMutex {
12 fn init() -> Box<Self> {
13 Box::new(AllocatedMutex(SpinMutex::new(WaitVariable::new(false))))
17 // Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
19 pub const fn new() -> Mutex {
20 Mutex { inner: LazyBox::new() }
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
31 // We are just now obtaining the lock
32 *guard.lock_var_mut() = true;
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;
43 // There was a thread waiting, just pass the lock
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
54 // We are just now obtaining the lock
55 *guard.lock_var_mut() = true;