1 use super::waitqueue
::{try_lock_or_false, SpinMutex, WaitQueue, WaitVariable}
;
2 use crate::sys_common
::lazy_box
::{LazyBox, LazyInit}
;
5 inner
: SpinMutex
<WaitVariable
<bool
>>,
8 // not movable: see UnsafeList implementation
9 pub(crate) type MovableMutex
= LazyBox
<Mutex
>;
11 impl LazyInit
for Mutex
{
12 fn init() -> Box
<Self> {
17 // Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
19 pub const fn new() -> Mutex
{
20 Mutex { inner: SpinMutex::new(WaitVariable::new(false)) }
24 pub unsafe fn lock(&self) {
25 let mut guard
= self.inner
.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
.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 unsafe fn try_lock(&self) -> bool
{
49 let mut guard
= try_lock_or_false
!(self.inner
);
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;