aboutsummaryrefslogtreecommitdiff
path: root/embassy-sync/src/blocking_mutex
diff options
context:
space:
mode:
authorDion Dokter <[email protected]>2025-11-20 13:22:38 +0100
committerDion Dokter <[email protected]>2025-11-20 13:22:38 +0100
commit4f2c36e447455e8d33607d586859d3d075cabf1d (patch)
tree003cd822d688acd7c074dd229663b4648d100f71 /embassy-sync/src/blocking_mutex
parent663732d85abbae400f2dbab2c411802a5b60e9b1 (diff)
parent661874d11de7d93ed52e08e020a9d4c7ee11122d (diff)
Merge branch 'main' into u0-lcd
Diffstat (limited to 'embassy-sync/src/blocking_mutex')
-rw-r--r--embassy-sync/src/blocking_mutex/mod.rs23
-rw-r--r--embassy-sync/src/blocking_mutex/raw.rs6
2 files changed, 25 insertions, 4 deletions
diff --git a/embassy-sync/src/blocking_mutex/mod.rs b/embassy-sync/src/blocking_mutex/mod.rs
index 8a4a4c642..62bfc26fb 100644
--- a/embassy-sync/src/blocking_mutex/mod.rs
+++ b/embassy-sync/src/blocking_mutex/mod.rs
@@ -22,6 +22,7 @@ use self::raw::RawMutex;
22/// 22///
23/// In all cases, the blocking mutex is intended to be short lived and not held across await points. 23/// In all cases, the blocking mutex is intended to be short lived and not held across await points.
24/// Use the async [`Mutex`](crate::mutex::Mutex) if you need a lock that is held across await points. 24/// Use the async [`Mutex`](crate::mutex::Mutex) if you need a lock that is held across await points.
25#[derive(Debug)]
25pub struct Mutex<R, T: ?Sized> { 26pub struct Mutex<R, T: ?Sized> {
26 // NOTE: `raw` must be FIRST, so when using ThreadModeMutex the "can't drop in non-thread-mode" gets 27 // NOTE: `raw` must be FIRST, so when using ThreadModeMutex the "can't drop in non-thread-mode" gets
27 // to run BEFORE dropping `data`. 28 // to run BEFORE dropping `data`.
@@ -50,6 +51,23 @@ impl<R: RawMutex, T> Mutex<R, T> {
50 f(inner) 51 f(inner)
51 }) 52 })
52 } 53 }
54
55 /// Creates a critical section and grants temporary mutable access to the protected data.
56 ///
57 /// # Safety
58 ///
59 /// This method is marked unsafe because calling this method re-entrantly, i.e. within
60 /// another `lock_mut` or `lock` closure, violates Rust's aliasing rules. Calling this
61 /// method at the same time from different tasks is safe. For a safe alternative with
62 /// mutable access that never causes UB, use a `RefCell` in a `Mutex`.
63 pub unsafe fn lock_mut<U>(&self, f: impl FnOnce(&mut T) -> U) -> U {
64 self.raw.lock(|| {
65 let ptr = self.data.get() as *mut T;
66 // Safety: we have exclusive access to the data, as long as this mutex is not locked re-entrantly
67 let inner = unsafe { &mut *ptr };
68 f(inner)
69 })
70 }
53} 71}
54 72
55impl<R, T> Mutex<R, T> { 73impl<R, T> Mutex<R, T> {
@@ -104,6 +122,7 @@ impl<T> Mutex<raw::CriticalSectionRawMutex, T> {
104 122
105impl<T> Mutex<raw::NoopRawMutex, T> { 123impl<T> Mutex<raw::NoopRawMutex, T> {
106 /// Borrows the data 124 /// Borrows the data
125 #[allow(clippy::should_implement_trait)]
107 pub fn borrow(&self) -> &T { 126 pub fn borrow(&self) -> &T {
108 let ptr = self.data.get() as *const T; 127 let ptr = self.data.get() as *const T;
109 unsafe { &*ptr } 128 unsafe { &*ptr }
@@ -116,9 +135,9 @@ impl<T> Mutex<raw::NoopRawMutex, T> {
116// There's still a ThreadModeRawMutex for use with the generic Mutex (handy with Channel, for example), 135// There's still a ThreadModeRawMutex for use with the generic Mutex (handy with Channel, for example),
117// but that will require T: Send even though it shouldn't be needed. 136// but that will require T: Send even though it shouldn't be needed.
118 137
119#[cfg(any(cortex_m, feature = "std"))] 138#[cfg(any(cortex_m, doc, feature = "std"))]
120pub use thread_mode_mutex::*; 139pub use thread_mode_mutex::*;
121#[cfg(any(cortex_m, feature = "std"))] 140#[cfg(any(cortex_m, doc, feature = "std"))]
122mod thread_mode_mutex { 141mod thread_mode_mutex {
123 use super::*; 142 use super::*;
124 143
diff --git a/embassy-sync/src/blocking_mutex/raw.rs b/embassy-sync/src/blocking_mutex/raw.rs
index a8afcad34..fbb9ece15 100644
--- a/embassy-sync/src/blocking_mutex/raw.rs
+++ b/embassy-sync/src/blocking_mutex/raw.rs
@@ -37,6 +37,7 @@ pub unsafe trait RawMutex {
37/// # Safety 37/// # Safety
38/// 38///
39/// This mutex is safe to share between different executors and interrupts. 39/// This mutex is safe to share between different executors and interrupts.
40#[derive(Debug)]
40pub struct CriticalSectionRawMutex { 41pub struct CriticalSectionRawMutex {
41 _phantom: PhantomData<()>, 42 _phantom: PhantomData<()>,
42} 43}
@@ -65,6 +66,7 @@ unsafe impl RawMutex for CriticalSectionRawMutex {
65/// # Safety 66/// # Safety
66/// 67///
67/// **This Mutex is only safe within a single executor.** 68/// **This Mutex is only safe within a single executor.**
69#[derive(Debug)]
68pub struct NoopRawMutex { 70pub struct NoopRawMutex {
69 _phantom: PhantomData<*mut ()>, 71 _phantom: PhantomData<*mut ()>,
70} 72}
@@ -87,7 +89,7 @@ unsafe impl RawMutex for NoopRawMutex {
87 89
88// ================ 90// ================
89 91
90#[cfg(any(cortex_m, feature = "std"))] 92#[cfg(any(cortex_m, doc, feature = "std"))]
91mod thread_mode { 93mod thread_mode {
92 use super::*; 94 use super::*;
93 95
@@ -145,5 +147,5 @@ mod thread_mode {
145 return unsafe { (0xE000ED04 as *const u32).read_volatile() } & 0x1FF == 0; 147 return unsafe { (0xE000ED04 as *const u32).read_volatile() } & 0x1FF == 0;
146 } 148 }
147} 149}
148#[cfg(any(cortex_m, feature = "std"))] 150#[cfg(any(cortex_m, doc, feature = "std"))]
149pub use thread_mode::*; 151pub use thread_mode::*;