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 ;
3
3
4
4
pub struct RwLock {
5
5
/// The "mode" value indicates how many threads are waiting on this
@@ -14,59 +14,61 @@ pub struct RwLock {
14
14
mode : AtomicIsize ,
15
15
}
16
16
17
+ const RWLOCK_WRITING : isize = -1 ;
18
+ const RWLOCK_FREE : isize = 0 ;
19
+
17
20
unsafe impl Send for RwLock { }
18
21
unsafe impl Sync for RwLock { }
19
22
20
23
impl RwLock {
21
24
#[ inline]
22
25
#[ rustc_const_stable( feature = "const_locks" , since = "1.63.0" ) ]
23
26
pub const fn new ( ) -> RwLock {
24
- RwLock { mode : AtomicIsize :: new ( 0 ) }
27
+ RwLock { mode : AtomicIsize :: new ( RWLOCK_FREE ) }
25
28
}
26
29
27
30
#[ inline]
28
31
pub unsafe fn read ( & self ) {
29
32
while !unsafe { self . try_read ( ) } {
30
- do_yield ( ) ;
33
+ yield_now ( ) ;
31
34
}
32
35
}
33
36
34
37
#[ inline]
35
38
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 ( )
49
46
}
50
47
51
48
#[ inline]
52
49
pub unsafe fn write ( & self ) {
53
50
while !unsafe { self . try_write ( ) } {
54
- do_yield ( ) ;
51
+ yield_now ( ) ;
55
52
}
56
53
}
57
54
58
55
#[ inline]
59
56
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 ( )
61
58
}
62
59
63
60
#[ inline]
64
61
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 ) ;
66
65
}
67
66
68
67
#[ inline]
69
68
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
+ ) ;
71
73
}
72
74
}
0 commit comments