diff --git a/Cargo.toml b/Cargo.toml index e7cc078..d4f49cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ categories = ["rust-patterns", "no-std"] exclusive_cell = "0.1" generic_once_cell = "0.1" interrupts = "0.1" +interrupt-mutex = "0.1" lock_api = "0.4" [dev-dependencies] diff --git a/src/lib.rs b/src/lib.rs index 73f4b49..a2758c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,8 +93,8 @@ pub(crate) mod mutex; pub(crate) mod rwlock; pub use exclusive_cell::{CallOnce, CallOnceError, ExclusiveCell}; +pub use interrupt_mutex::{InterruptMutex, InterruptMutexGuard, RawInterruptMutex}; pub use interrupts::without as without_interrupts; -pub use mutex::interrupt::{InterruptMutex, InterruptMutexGuard, RawInterruptMutex}; pub use mutex::spin::{RawSpinMutex, SpinMutex, SpinMutexGuard}; pub use mutex::ticket::{RawTicketMutex, TicketMutex, TicketMutexGuard}; pub use mutex::{ diff --git a/src/mutex/interrupt.rs b/src/mutex/interrupt.rs deleted file mode 100644 index 4e147ff..0000000 --- a/src/mutex/interrupt.rs +++ /dev/null @@ -1,74 +0,0 @@ -use core::cell::UnsafeCell; -use core::mem::MaybeUninit; - -use lock_api::{GuardNoSend, RawMutex}; - -/// An interrupt-safe mutex. -/// -/// This mutex wraps another [`RawMutex`] and disables interrupts while locked. -/// Only has an effect if `target_os = "none"`. -pub struct RawInterruptMutex { - inner: I, - interrupt_guard: UnsafeCell>, -} - -// SAFETY: The `UnsafeCell` is locked by `inner`, initialized on `lock` and uninitialized on `unlock`. -unsafe impl Sync for RawInterruptMutex {} -// SAFETY: Mutexes cannot be send to other threads while locked. -// Sending them while unlocked is fine. -unsafe impl Send for RawInterruptMutex {} - -unsafe impl RawMutex for RawInterruptMutex { - 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(); - // SAFETY: We have exclusive access through locking `inner`. - 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 { - // SAFETY: We have exclusive access through locking `inner`. - unsafe { - self.interrupt_guard.get().write(MaybeUninit::new(guard)); - } - } - ok - } - - #[inline] - unsafe fn unlock(&self) { - // SAFETY: We have exclusive access through locking `inner`. - let guard = unsafe { self.interrupt_guard.get().replace(MaybeUninit::uninit()) }; - // SAFETY: `guard` was initialized when locking. - let guard = unsafe { guard.assume_init() }; - unsafe { - self.inner.unlock(); - } - drop(guard); - } - - #[inline] - fn is_locked(&self) -> bool { - self.inner.is_locked() - } -} - -/// A [`lock_api::Mutex`] based on [`RawInterruptMutex`]. -pub type InterruptMutex = lock_api::Mutex, T>; - -/// A [`lock_api::MutexGuard`] based on [`RawInterruptMutex`]. -pub type InterruptMutexGuard<'a, I, T> = lock_api::MutexGuard<'a, RawInterruptMutex, T>; diff --git a/src/mutex/mod.rs b/src/mutex/mod.rs index 206d45d..c8cf0b4 100644 --- a/src/mutex/mod.rs +++ b/src/mutex/mod.rs @@ -1,8 +1,7 @@ -pub(crate) mod interrupt; pub(crate) mod spin; pub(crate) mod ticket; -use interrupt::RawInterruptMutex; +use interrupt_mutex::RawInterruptMutex; use spin::RawSpinMutex; use ticket::RawTicketMutex;