// TODO: Share code for simple futex-based mutex between relibc's Mutex<()> and this. use core::{ cell::UnsafeCell, ops::{Deref, DerefMut}, sync::atomic::{AtomicU32, Ordering}, }; pub struct Mutex { pub lockword: AtomicU32, pub inner: UnsafeCell, } const UNLOCKED: u32 = 0; const LOCKED: u32 = 1; const WAITING: u32 = 2; unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} impl Mutex { pub const fn new(t: T) -> Self { Self { lockword: AtomicU32::new(0), inner: UnsafeCell::new(t), } } pub fn lock(&self) -> MutexGuard<'_, T> { while self .lockword .compare_exchange(UNLOCKED, LOCKED, Ordering::Acquire, Ordering::Relaxed) .is_err() { core::hint::spin_loop(); } MutexGuard { lock: self } } } pub struct MutexGuard<'l, T> { lock: &'l Mutex, } impl Deref for MutexGuard<'_, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.lock.inner.get() } } } impl DerefMut for MutexGuard<'_, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.lock.inner.get() } } } impl Drop for MutexGuard<'_, T> { fn drop(&mut self) { self.lock.lockword.store(UNLOCKED, Ordering::Release); } }