1
1
use crate :: sync:: atomic:: {
2
- AtomicI32 ,
2
+ AtomicU32 ,
3
3
Ordering :: { Acquire , Relaxed , Release } ,
4
4
} ;
5
5
use crate :: sys:: futex:: { futex_wait, futex_wake, futex_wake_all} ;
@@ -14,36 +14,36 @@ pub struct RwLock {
14
14
// 0x3FFF_FFFF: Write locked
15
15
// Bit 30: Readers are waiting on this futex.
16
16
// Bit 31: Writers are waiting on the writer_notify futex.
17
- state : AtomicI32 ,
17
+ state : AtomicU32 ,
18
18
// The 'condition variable' to notify writers through.
19
19
// Incremented on every signal.
20
- writer_notify : AtomicI32 ,
20
+ writer_notify : AtomicU32 ,
21
21
}
22
22
23
- const READ_LOCKED : i32 = 1 ;
24
- const MASK : i32 = ( 1 << 30 ) - 1 ;
25
- const WRITE_LOCKED : i32 = MASK ;
26
- const MAX_READERS : i32 = MASK - 1 ;
27
- const READERS_WAITING : i32 = 1 << 30 ;
28
- const WRITERS_WAITING : i32 = 1 << 31 ;
23
+ const READ_LOCKED : u32 = 1 ;
24
+ const MASK : u32 = ( 1 << 30 ) - 1 ;
25
+ const WRITE_LOCKED : u32 = MASK ;
26
+ const MAX_READERS : u32 = MASK - 1 ;
27
+ const READERS_WAITING : u32 = 1 << 30 ;
28
+ const WRITERS_WAITING : u32 = 1 << 31 ;
29
29
30
- fn is_unlocked ( state : i32 ) -> bool {
30
+ fn is_unlocked ( state : u32 ) -> bool {
31
31
state & MASK == 0
32
32
}
33
33
34
- fn is_write_locked ( state : i32 ) -> bool {
34
+ fn is_write_locked ( state : u32 ) -> bool {
35
35
state & MASK == WRITE_LOCKED
36
36
}
37
37
38
- fn has_readers_waiting ( state : i32 ) -> bool {
38
+ fn has_readers_waiting ( state : u32 ) -> bool {
39
39
state & READERS_WAITING != 0
40
40
}
41
41
42
- fn has_writers_waiting ( state : i32 ) -> bool {
42
+ fn has_writers_waiting ( state : u32 ) -> bool {
43
43
state & WRITERS_WAITING != 0
44
44
}
45
45
46
- fn is_read_lockable ( state : i32 ) -> bool {
46
+ fn is_read_lockable ( state : u32 ) -> bool {
47
47
// This also returns false if the counter could overflow if we tried to read lock it.
48
48
//
49
49
// We don't allow read-locking if there's readers waiting, even if the lock is unlocked
@@ -53,14 +53,14 @@ fn is_read_lockable(state: i32) -> bool {
53
53
state & MASK < MAX_READERS && !has_readers_waiting ( state) && !has_writers_waiting ( state)
54
54
}
55
55
56
- fn has_reached_max_readers ( state : i32 ) -> bool {
56
+ fn has_reached_max_readers ( state : u32 ) -> bool {
57
57
state & MASK == MAX_READERS
58
58
}
59
59
60
60
impl RwLock {
61
61
#[ inline]
62
62
pub const fn new ( ) -> Self {
63
- Self { state : AtomicI32 :: new ( 0 ) , writer_notify : AtomicI32 :: new ( 0 ) }
63
+ Self { state : AtomicU32 :: new ( 0 ) , writer_notify : AtomicU32 :: new ( 0 ) }
64
64
}
65
65
66
66
#[ inline]
@@ -227,7 +227,7 @@ impl RwLock {
227
227
/// If both are waiting, this will wake up only one writer, but will fall
228
228
/// back to waking up readers if there was no writer to wake up.
229
229
#[ cold]
230
- fn wake_writer_or_readers ( & self , mut state : i32 ) {
230
+ fn wake_writer_or_readers ( & self , mut state : u32 ) {
231
231
assert ! ( is_unlocked( state) ) ;
232
232
233
233
// The readers waiting bit might be turned on at any point now,
@@ -287,7 +287,7 @@ impl RwLock {
287
287
}
288
288
289
289
/// Spin for a while, but stop directly at the given condition.
290
- fn spin_until ( & self , f : impl Fn ( i32 ) -> bool ) -> i32 {
290
+ fn spin_until ( & self , f : impl Fn ( u32 ) -> bool ) -> u32 {
291
291
let mut spin = 100 ; // Chosen by fair dice roll.
292
292
loop {
293
293
let state = self . state . load ( Relaxed ) ;
@@ -299,12 +299,12 @@ impl RwLock {
299
299
}
300
300
}
301
301
302
- fn spin_write ( & self ) -> i32 {
302
+ fn spin_write ( & self ) -> u32 {
303
303
// Stop spinning when it's unlocked or when there's waiting writers, to keep things somewhat fair.
304
304
self . spin_until ( |state| is_unlocked ( state) || has_writers_waiting ( state) )
305
305
}
306
306
307
- fn spin_read ( & self ) -> i32 {
307
+ fn spin_read ( & self ) -> u32 {
308
308
// Stop spinning when it's unlocked or read locked, or when there's waiting threads.
309
309
self . spin_until ( |state| {
310
310
!is_write_locked ( state) || has_readers_waiting ( state) || has_writers_waiting ( state)
0 commit comments