about summary refs log tree commit diff
path: root/library/std/src/sys/sync/mutex/sgx.rs
blob: 3eb981bc65af646bb61150639f528bc0caf5790e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use crate::sys::pal::waitqueue::{SpinMutex, WaitQueue, WaitVariable, try_lock_or_false};
use crate::sys::sync::OnceBox;

pub struct Mutex {
    // FIXME: `UnsafeList` is not movable.
    inner: OnceBox<SpinMutex<WaitVariable<bool>>>,
}

// Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
impl Mutex {
    pub const fn new() -> Mutex {
        Mutex { inner: OnceBox::new() }
    }

    fn get(&self) -> &SpinMutex<WaitVariable<bool>> {
        self.inner.get_or_init(|| Box::pin(SpinMutex::new(WaitVariable::new(false)))).get_ref()
    }

    #[inline]
    pub fn lock(&self) {
        let mut guard = self.get().lock();
        if *guard.lock_var() {
            // Another thread has the lock, wait
            WaitQueue::wait(guard, || {})
        // Another thread has passed the lock to us
        } else {
            // We are just now obtaining the lock
            *guard.lock_var_mut() = true;
        }
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        // SAFETY: the mutex was locked by the current thread, so it has been
        // initialized already.
        let guard = unsafe { self.inner.get_unchecked().get_ref().lock() };
        if let Err(mut guard) = WaitQueue::notify_one(guard) {
            // No other waiters, unlock
            *guard.lock_var_mut() = false;
        } else {
            // There was a thread waiting, just pass the lock
        }
    }

    #[inline]
    pub fn try_lock(&self) -> bool {
        let mut guard = try_lock_or_false!(self.get());
        if *guard.lock_var() {
            // Another thread has the lock
            false
        } else {
            // We are just now obtaining the lock
            *guard.lock_var_mut() = true;
            true
        }
    }
}