diff options
| -rw-r--r-- | embassy/src/blocking_mutex/raw.rs | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/embassy/src/blocking_mutex/raw.rs b/embassy/src/blocking_mutex/raw.rs index bdb443e4d..cbd00c565 100644 --- a/embassy/src/blocking_mutex/raw.rs +++ b/embassy/src/blocking_mutex/raw.rs | |||
| @@ -3,12 +3,32 @@ | |||
| 3 | //! This module provides a trait for mutexes that can be used in different contexts. | 3 | //! This module provides a trait for mutexes that can be used in different contexts. |
| 4 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 5 | 5 | ||
| 6 | /// Any object implementing this trait guarantees exclusive access to the data contained | 6 | /// Raw mutex trait. |
| 7 | /// within the mutex for the duration of the lock. | 7 | /// |
| 8 | /// Adapted from <https://github.com/rust-embedded/mutex-trait>. | 8 | /// This mutex is "raw", which means it does not actually contain the protected data, it |
| 9 | pub trait RawMutex { | 9 | /// just implements the mutex mechanism. For most uses you should use [`super::Mutex`] instead, |
| 10 | /// which is generic over a RawMutex and contains the protected data. | ||
| 11 | /// | ||
| 12 | /// Note that, unlike other mutexes, implementations only guarantee no | ||
| 13 | /// concurrent access from other threads: concurrent access from the current | ||
| 14 | /// thread is allwed. For example, it's possible to lock the same mutex multiple times reentrantly. | ||
| 15 | /// | ||
| 16 | /// Therefore, locking a `RawMutex` is only enough to guarantee safe shared (`&`) access | ||
| 17 | /// to the data, it is not enough to guarantee exclusive (`&mut`) access. | ||
| 18 | /// | ||
| 19 | /// # Safety | ||
| 20 | /// | ||
| 21 | /// RawMutex implementations must ensure that, while locked, no other thread can lock | ||
| 22 | /// the RawMutex concurrently. | ||
| 23 | /// | ||
| 24 | /// Unsafe code is allowed to rely on this fact, so incorrect implementations will cause undefined behavior. | ||
| 25 | pub unsafe trait RawMutex { | ||
| 26 | /// Create a new `RawMutex` instance. | ||
| 27 | /// | ||
| 28 | /// This is a const instead of a method to allow creating instances in const context. | ||
| 10 | const INIT: Self; | 29 | const INIT: Self; |
| 11 | 30 | ||
| 31 | /// Lock this `RawMutex`. | ||
| 12 | fn lock<R>(&self, f: impl FnOnce() -> R) -> R; | 32 | fn lock<R>(&self, f: impl FnOnce() -> R) -> R; |
| 13 | } | 33 | } |
| 14 | 34 | ||
| @@ -29,7 +49,7 @@ impl CriticalSectionRawMutex { | |||
| 29 | } | 49 | } |
| 30 | } | 50 | } |
| 31 | 51 | ||
| 32 | impl RawMutex for CriticalSectionRawMutex { | 52 | unsafe impl RawMutex for CriticalSectionRawMutex { |
| 33 | const INIT: Self = Self::new(); | 53 | const INIT: Self = Self::new(); |
| 34 | 54 | ||
| 35 | fn lock<R>(&self, f: impl FnOnce() -> R) -> R { | 55 | fn lock<R>(&self, f: impl FnOnce() -> R) -> R { |
| @@ -56,7 +76,7 @@ impl NoopRawMutex { | |||
| 56 | } | 76 | } |
| 57 | } | 77 | } |
| 58 | 78 | ||
| 59 | impl RawMutex for NoopRawMutex { | 79 | unsafe impl RawMutex for NoopRawMutex { |
| 60 | const INIT: Self = Self::new(); | 80 | const INIT: Self = Self::new(); |
| 61 | fn lock<R>(&self, f: impl FnOnce() -> R) -> R { | 81 | fn lock<R>(&self, f: impl FnOnce() -> R) -> R { |
| 62 | f() | 82 | f() |
| @@ -89,7 +109,7 @@ mod thread_mode { | |||
| 89 | } | 109 | } |
| 90 | } | 110 | } |
| 91 | 111 | ||
| 92 | impl RawMutex for ThreadModeRawMutex { | 112 | unsafe impl RawMutex for ThreadModeRawMutex { |
| 93 | const INIT: Self = Self::new(); | 113 | const INIT: Self = Self::new(); |
| 94 | fn lock<R>(&self, f: impl FnOnce() -> R) -> R { | 114 | fn lock<R>(&self, f: impl FnOnce() -> R) -> R { |
| 95 | assert!(in_thread_mode(), "ThreadModeMutex can only be locked from thread mode."); | 115 | assert!(in_thread_mode(), "ThreadModeMutex can only be locked from thread mode."); |
