7272
7373use core:: marker:: PhantomData ;
7474use core:: sync:: atomic:: { AtomicBool , Ordering } ;
75- use mutex_traits:: { ConstInit , ScopedRawMutex } ;
75+ use mutex_traits:: { ConstInit , RawMutex , ScopedRawMutex } ;
7676
7777pub use mutex_traits as traits;
7878
@@ -170,32 +170,61 @@ pub mod local {
170170 const INIT : Self = Self :: new ( ) ;
171171 }
172172
173- unsafe impl ScopedRawMutex for LocalRawMutex {
173+ unsafe impl RawMutex for LocalRawMutex {
174+ type GuardMarker = * mut ( ) ;
175+
174176 #[ inline]
175- fn try_with_lock < R > ( & self , f : impl FnOnce ( ) -> R ) -> Option < R > {
176- // NOTE: separated load/stores are acceptable as we are !Sync,
177- // meaning that we can only be accessed within a single thread
178- if self . taken . load ( Ordering :: Relaxed ) {
179- return None ;
177+ fn lock ( & self ) {
178+ if !self . try_lock ( ) {
179+ // In a local-only mutex, it is not possible for another holder
180+ // of this mutex to release, which means we have certainly
181+ // reached deadlock if the lock was already locked.
182+ panic ! ( "Deadlocked" ) ;
180183 }
181- self . taken . store ( true , Ordering :: Relaxed ) ;
182- let ret = f ( ) ;
183- self . taken . store ( false , Ordering :: Relaxed ) ;
184- Some ( ret)
185184 }
186185
187186 #[ inline]
188- fn with_lock < R > ( & self , f : impl FnOnce ( ) -> R ) -> R {
189- // In a local-only mutex, it is not possible for another holder
190- // of this mutex to release, which means we have certainly
191- // reached deadlock if the lock was already locked.
192- self . try_with_lock ( f) . expect ( "Deadlocked" )
187+ fn try_lock ( & self ) -> bool {
188+ self . taken
189+ . compare_exchange ( false , true , Ordering :: AcqRel , Ordering :: Relaxed )
190+ . is_ok ( )
193191 }
194192
193+ #[ inline]
194+ unsafe fn unlock ( & self ) {
195+ self . taken . store ( false , Ordering :: Release ) ;
196+ }
197+
198+ #[ inline]
195199 fn is_locked ( & self ) -> bool {
196200 self . taken . load ( Ordering :: Relaxed )
197201 }
198202 }
203+
204+ #[ cfg( feature = "std" ) ]
205+ #[ cfg( test) ]
206+ mod test {
207+ use super :: * ;
208+ use crate :: BlockingMutex ;
209+
210+ #[ test]
211+ fn local_raw_mutex ( ) {
212+ let mutex = BlockingMutex :: < LocalRawMutex , u32 > :: new ( 0 ) ;
213+ let mut guard = mutex. lock ( ) ;
214+ assert_eq ! ( * guard, 0 ) ;
215+ * guard = 1 ;
216+ drop ( guard) ;
217+
218+ let mut guard = mutex. lock ( ) ;
219+ assert_eq ! ( * guard, 1 ) ;
220+ * guard = 2 ;
221+ drop ( guard) ;
222+
223+ mutex. with_lock ( |data| {
224+ assert_eq ! ( * data, 2 ) ;
225+ } ) ;
226+ }
227+ }
199228}
200229
201230// ================
@@ -210,7 +239,7 @@ pub mod single_core_thread_mode {
210239 ///
211240 /// # Safety
212241 ///
213- /// **This Mutex is only safe on single-core systems.**
242+ /// **This Mutex is only safe on single-core bare-metal systems.**
214243 ///
215244 /// On multi-core systems, a `ThreadModeRawMutex` **is not sufficient** to ensure exclusive access.
216245 #[ cfg_attr( feature = "fmt" , derive( Debug ) ) ]
@@ -234,30 +263,35 @@ pub mod single_core_thread_mode {
234263 const INIT : Self = Self :: new ( ) ;
235264 }
236265
237- unsafe impl ScopedRawMutex for ThreadModeRawMutex {
266+ unsafe impl RawMutex for ThreadModeRawMutex {
267+ type GuardMarker = * mut ( ) ;
268+
238269 #[ inline]
239- fn try_with_lock < R > ( & self , f : impl FnOnce ( ) -> R ) -> Option < R > {
270+ fn lock ( & self ) {
271+ if !self . try_lock ( ) {
272+ // In a thread-mode only mutex, it is not possible for another holder
273+ // of this mutex to release, which means we have certainly
274+ // reached deadlock if the lock was already locked.
275+ panic ! ( "Deadlocked or attempted to access outside of thread mode" )
276+ }
277+ }
278+
279+ #[ inline]
280+ fn try_lock ( & self ) -> bool {
240281 if !in_thread_mode ( ) {
241- return None ;
282+ return false ;
242283 }
243- // NOTE: separated load/stores are acceptable as we checked we are only
244- // accessed from a single thread (checked above)
245- assert ! ( !self . taken. load( Ordering :: Relaxed ) ) ;
246- self . taken . store ( true , Ordering :: Relaxed ) ;
247- let ret = f ( ) ;
248- self . taken . store ( false , Ordering :: Relaxed ) ;
249- Some ( ret)
284+ self . taken
285+ . compare_exchange ( false , true , Ordering :: AcqRel , Ordering :: Relaxed )
286+ . is_ok ( )
250287 }
251288
252289 #[ inline]
253- fn with_lock < R > ( & self , f : impl FnOnce ( ) -> R ) -> R {
254- // In a thread-mode only mutex, it is not possible for another holder
255- // of this mutex to release, which means we have certainly
256- // reached deadlock if the lock was already locked.
257- self . try_with_lock ( f)
258- . expect ( "Deadlocked or attempted to access outside of thread mode" )
290+ unsafe fn unlock ( & self ) {
291+ self . taken . store ( false , Ordering :: Release ) ;
259292 }
260293
294+ #[ inline]
261295 fn is_locked ( & self ) -> bool {
262296 self . taken . load ( Ordering :: Relaxed )
263297 }
0 commit comments