use core::cell::UnsafeCell;
use core::mem::MaybeUninit;
use lock_api::{GuardNoSend, RawMutex};
pub struct RawInterruptMutex<I> {
inner: I,
interrupt_guard: UnsafeCell<MaybeUninit<interrupts::Guard>>,
}
unsafe impl<I: Sync> Sync for RawInterruptMutex<I> {}
unsafe impl<I: Send> Send for RawInterruptMutex<I> {}
unsafe impl<I: RawMutex> RawMutex for RawInterruptMutex<I> {
const INIT: Self = Self {
inner: I::INIT,
interrupt_guard: UnsafeCell::new(MaybeUninit::uninit()),
};
type GuardMarker = GuardNoSend;
#[inline]
fn lock(&self) {
let guard = interrupts::disable();
self.inner.lock();
unsafe {
self.interrupt_guard.get().write(MaybeUninit::new(guard));
}
}
#[inline]
fn try_lock(&self) -> bool {
let guard = interrupts::disable();
let ok = self.inner.try_lock();
if ok {
unsafe {
self.interrupt_guard.get().write(MaybeUninit::new(guard));
}
}
ok
}
#[inline]
unsafe fn unlock(&self) {
let guard = unsafe { self.interrupt_guard.get().replace(MaybeUninit::uninit()) };
let guard = unsafe { guard.assume_init() };
unsafe {
self.inner.unlock();
}
drop(guard);
}
#[inline]
fn is_locked(&self) -> bool {
self.inner.is_locked()
}
}
pub type InterruptMutex<I, T> = lock_api::Mutex<RawInterruptMutex<I>, T>;
pub type InterruptMutexGuard<'a, I, T> = lock_api::MutexGuard<'a, RawInterruptMutex<I>, T>;