diff --git a/embassy-sync/src/blocking_mutex/mod.rs b/embassy-sync/src/blocking_mutex/mod.rs index beafdb43d..a41bc3569 100644 --- a/embassy-sync/src/blocking_mutex/mod.rs +++ b/embassy-sync/src/blocking_mutex/mod.rs @@ -50,6 +50,23 @@ impl Mutex { f(inner) }) } + + /// Creates a critical section and grants temporary mutable access to the protected data. + /// + /// # Safety + /// + /// This method is marked unsafe because calling this method re-entrantly, i.e. within + /// another `lock_mut` or `lock` closure, violates Rust's aliasing rules. Calling this + /// method at the same time from different tasks is safe. For a safe alternative with + /// mutable access that never causes UB, use a `RefCell` in a `Mutex`. + pub unsafe fn lock_mut(&self, f: impl FnOnce(&mut T) -> U) -> U { + self.raw.lock(|| { + let ptr = self.data.get() as *mut T; + // Safety: we have exclusive access to the data, as long as this mutex is not locked re-entrantly + let inner = unsafe { &mut *ptr }; + f(inner) + }) + } } impl Mutex {