1- use crate :: os :: xous :: ffi :: do_yield ;
2- use crate :: sync :: atomic :: { AtomicIsize , Ordering :: SeqCst } ;
1+ use crate :: sync :: atomic :: { AtomicIsize , Ordering :: Acquire } ;
2+ use crate :: thread :: yield_now ;
33
44pub struct RwLock {
55 /// The "mode" value indicates how many threads are waiting on this
@@ -14,59 +14,61 @@ pub struct RwLock {
1414 mode : AtomicIsize ,
1515}
1616
17+ const RWLOCK_WRITING : isize = -1 ;
18+ const RWLOCK_FREE : isize = 0 ;
19+
1720unsafe impl Send for RwLock { }
1821unsafe impl Sync for RwLock { }
1922
2023impl RwLock {
2124 #[ inline]
2225 #[ rustc_const_stable( feature = "const_locks" , since = "1.63.0" ) ]
2326 pub const fn new ( ) -> RwLock {
24- RwLock { mode : AtomicIsize :: new ( 0 ) }
27+ RwLock { mode : AtomicIsize :: new ( RWLOCK_FREE ) }
2528 }
2629
2730 #[ inline]
2831 pub unsafe fn read ( & self ) {
2932 while !unsafe { self . try_read ( ) } {
30- do_yield ( ) ;
33+ yield_now ( ) ;
3134 }
3235 }
3336
3437 #[ inline]
3538 pub unsafe fn try_read ( & self ) -> bool {
36- // Non-atomically determine the current value.
37- let current = self . mode . load ( SeqCst ) ;
38-
39- // If it's currently locked for writing, then we cannot read.
40- if current < 0 {
41- return false ;
42- }
43-
44- // Attempt to lock. If the `current` value has changed, then this
45- // operation will fail and we will not obtain the lock even if we
46- // could potentially keep it.
47- let new = current + 1 ;
48- self . mode . compare_exchange ( current, new, SeqCst , SeqCst ) . is_ok ( )
39+ self . mode
40+ . fetch_update (
41+ Acquire ,
42+ Acquire ,
43+ |v| if v == RWLOCK_WRITING { None } else { Some ( v + 1 ) } ,
44+ )
45+ . is_ok ( )
4946 }
5047
5148 #[ inline]
5249 pub unsafe fn write ( & self ) {
5350 while !unsafe { self . try_write ( ) } {
54- do_yield ( ) ;
51+ yield_now ( ) ;
5552 }
5653 }
5754
5855 #[ inline]
5956 pub unsafe fn try_write ( & self ) -> bool {
60- self . mode . compare_exchange ( 0 , - 1 , SeqCst , SeqCst ) . is_ok ( )
57+ self . mode . compare_exchange ( RWLOCK_FREE , RWLOCK_WRITING , Acquire , Acquire ) . is_ok ( )
6158 }
6259
6360 #[ inline]
6461 pub unsafe fn read_unlock ( & self ) {
65- self . mode . fetch_sub ( 1 , SeqCst ) ;
62+ let previous = self . mode . fetch_sub ( 1 , Acquire ) ;
63+ assert ! ( previous != RWLOCK_FREE ) ;
64+ assert ! ( previous != RWLOCK_WRITING ) ;
6665 }
6766
6867 #[ inline]
6968 pub unsafe fn write_unlock ( & self ) {
70- assert_eq ! ( self . mode. compare_exchange( -1 , 0 , SeqCst , SeqCst ) , Ok ( -1 ) ) ;
69+ assert_eq ! (
70+ self . mode. compare_exchange( RWLOCK_WRITING , RWLOCK_FREE , Acquire , Acquire ) ,
71+ Ok ( RWLOCK_WRITING )
72+ ) ;
7173 }
7274}
0 commit comments