diff --git a/embassy/src/blocking_mutex/raw.rs b/embassy/src/blocking_mutex/raw.rs index bdb443e4..cbd00c56 100644 --- a/embassy/src/blocking_mutex/raw.rs +++ b/embassy/src/blocking_mutex/raw.rs @@ -3,12 +3,32 @@ //! This module provides a trait for mutexes that can be used in different contexts. use core::marker::PhantomData; -/// Any object implementing this trait guarantees exclusive access to the data contained -/// within the mutex for the duration of the lock. -/// Adapted from . -pub trait RawMutex { +/// Raw mutex trait. +/// +/// This mutex is "raw", which means it does not actually contain the protected data, it +/// just implements the mutex mechanism. For most uses you should use [`super::Mutex`] instead, +/// which is generic over a RawMutex and contains the protected data. +/// +/// Note that, unlike other mutexes, implementations only guarantee no +/// concurrent access from other threads: concurrent access from the current +/// thread is allwed. For example, it's possible to lock the same mutex multiple times reentrantly. +/// +/// Therefore, locking a `RawMutex` is only enough to guarantee safe shared (`&`) access +/// to the data, it is not enough to guarantee exclusive (`&mut`) access. +/// +/// # Safety +/// +/// RawMutex implementations must ensure that, while locked, no other thread can lock +/// the RawMutex concurrently. +/// +/// Unsafe code is allowed to rely on this fact, so incorrect implementations will cause undefined behavior. +pub unsafe trait RawMutex { + /// Create a new `RawMutex` instance. + /// + /// This is a const instead of a method to allow creating instances in const context. const INIT: Self; + /// Lock this `RawMutex`. fn lock(&self, f: impl FnOnce() -> R) -> R; } @@ -29,7 +49,7 @@ impl CriticalSectionRawMutex { } } -impl RawMutex for CriticalSectionRawMutex { +unsafe impl RawMutex for CriticalSectionRawMutex { const INIT: Self = Self::new(); fn lock(&self, f: impl FnOnce() -> R) -> R { @@ -56,7 +76,7 @@ impl NoopRawMutex { } } -impl RawMutex for NoopRawMutex { +unsafe impl RawMutex for NoopRawMutex { const INIT: Self = Self::new(); fn lock(&self, f: impl FnOnce() -> R) -> R { f() @@ -89,7 +109,7 @@ mod thread_mode { } } - impl RawMutex for ThreadModeRawMutex { + unsafe impl RawMutex for ThreadModeRawMutex { const INIT: Self = Self::new(); fn lock(&self, f: impl FnOnce() -> R) -> R { assert!(in_thread_mode(), "ThreadModeMutex can only be locked from thread mode.");