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,72 @@ 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+ #[ cfg( armv6m) ]
189+ {
190+ // NOTE: separated load/stores are acceptable as we are !Sync,
191+ // meaning that we can only be accessed within a single thread
192+ if self . taken . load ( Ordering :: Relaxed ) {
193+ return false ;
194+ }
195+ self . taken . store ( true , Ordering :: Relaxed ) ;
196+ return true ;
197+ }
198+ #[ cfg( not( armv6m) ) ]
199+ self . taken
200+ . compare_exchange ( false , true , Ordering :: AcqRel , Ordering :: Relaxed )
201+ . is_ok ( )
193202 }
194203
204+ #[ inline]
205+ unsafe fn unlock ( & self ) {
206+ self . taken . store ( false , Ordering :: Release ) ;
207+ }
208+
209+ #[ inline]
195210 fn is_locked ( & self ) -> bool {
196211 self . taken . load ( Ordering :: Relaxed )
197212 }
198213 }
214+
215+ #[ cfg( feature = "std" ) ]
216+ #[ cfg( test) ]
217+ mod test {
218+ use super :: * ;
219+ use crate :: BlockingMutex ;
220+
221+ #[ test]
222+ fn local_raw_mutex ( ) {
223+ let mutex = BlockingMutex :: < LocalRawMutex , u32 > :: new ( 0 ) ;
224+ let mut guard = mutex. lock ( ) ;
225+ assert_eq ! ( * guard, 0 ) ;
226+ * guard = 1 ;
227+ drop ( guard) ;
228+
229+ let mut guard = mutex. lock ( ) ;
230+ assert_eq ! ( * guard, 1 ) ;
231+ * guard = 2 ;
232+ drop ( guard) ;
233+
234+ mutex. with_lock ( |data| {
235+ assert_eq ! ( * data, 2 ) ;
236+ } ) ;
237+ }
238+ }
199239}
200240
201241// ================
@@ -210,7 +250,7 @@ pub mod single_core_thread_mode {
210250 ///
211251 /// # Safety
212252 ///
213- /// **This Mutex is only safe on single-core systems.**
253+ /// **This Mutex is only safe on single-core bare-metal systems.**
214254 ///
215255 /// On multi-core systems, a `ThreadModeRawMutex` **is not sufficient** to ensure exclusive access.
216256 #[ cfg_attr( feature = "fmt" , derive( Debug ) ) ]
@@ -234,30 +274,44 @@ pub mod single_core_thread_mode {
234274 const INIT : Self = Self :: new ( ) ;
235275 }
236276
237- unsafe impl ScopedRawMutex for ThreadModeRawMutex {
277+ unsafe impl RawMutex for ThreadModeRawMutex {
278+ type GuardMarker = * mut ( ) ;
279+
238280 #[ inline]
239- fn try_with_lock < R > ( & self , f : impl FnOnce ( ) -> R ) -> Option < R > {
281+ fn lock ( & self ) {
282+ if !self . try_lock ( ) {
283+ // In a thread-mode only mutex, it is not possible for another holder
284+ // of this mutex to release, which means we have certainly
285+ // reached deadlock if the lock was already locked.
286+ panic ! ( "Deadlocked or attempted to access outside of thread mode" )
287+ }
288+ }
289+
290+ #[ inline]
291+ fn try_lock ( & self ) -> bool {
240292 if !in_thread_mode ( ) {
241- return None ;
293+ return false ;
294+ }
295+ #[ cfg( armv6m) ]
296+ {
297+ // NOTE: separated load/stores are acceptable as we checked we are only
298+ // accessed from a single thread (checked above)
299+ assert ! ( !self . taken. load( Ordering :: Relaxed ) ) ;
300+ self . taken . store ( true , Ordering :: Relaxed ) ;
301+ return true ;
242302 }
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)
303+ #[ cfg( not( armv6m) ) ]
304+ self . taken
305+ . compare_exchange ( false , true , Ordering :: AcqRel , Ordering :: Relaxed )
306+ . is_ok ( )
250307 }
251308
252309 #[ 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" )
310+ unsafe fn unlock ( & self ) {
311+ self . taken . store ( false , Ordering :: Release ) ;
259312 }
260313
314+ #[ inline]
261315 fn is_locked ( & self ) -> bool {
262316 self . taken . load ( Ordering :: Relaxed )
263317 }
0 commit comments