1- use crate :: sync:: atomic:: AtomicU32 ;
21use crate :: sync:: atomic:: Ordering :: { Acquire , Relaxed , Release } ;
3- use crate :: sys:: futex:: { futex_wait, futex_wake, futex_wake_all} ;
2+ use crate :: sys:: futex:: { Futex , Primitive , futex_wait, futex_wake, futex_wake_all} ;
43
54pub struct RwLock {
65 // The state consists of a 30-bit reader counter, a 'readers waiting' flag, and a 'writers waiting' flag.
@@ -10,41 +9,41 @@ pub struct RwLock {
109 // 0x3FFF_FFFF: Write locked
1110 // Bit 30: Readers are waiting on this futex.
1211 // Bit 31: Writers are waiting on the writer_notify futex.
13- state : AtomicU32 ,
12+ state : Futex ,
1413 // The 'condition variable' to notify writers through.
1514 // Incremented on every signal.
16- writer_notify : AtomicU32 ,
15+ writer_notify : Futex ,
1716}
1817
19- const READ_LOCKED : u32 = 1 ;
20- const MASK : u32 = ( 1 << 30 ) - 1 ;
21- const WRITE_LOCKED : u32 = MASK ;
22- const MAX_READERS : u32 = MASK - 1 ;
23- const READERS_WAITING : u32 = 1 << 30 ;
24- const WRITERS_WAITING : u32 = 1 << 31 ;
18+ const READ_LOCKED : Primitive = 1 ;
19+ const MASK : Primitive = ( 1 << 30 ) - 1 ;
20+ const WRITE_LOCKED : Primitive = MASK ;
21+ const MAX_READERS : Primitive = MASK - 1 ;
22+ const READERS_WAITING : Primitive = 1 << 30 ;
23+ const WRITERS_WAITING : Primitive = 1 << 31 ;
2524
2625#[ inline]
27- fn is_unlocked ( state : u32 ) -> bool {
26+ fn is_unlocked ( state : Primitive ) -> bool {
2827 state & MASK == 0
2928}
3029
3130#[ inline]
32- fn is_write_locked ( state : u32 ) -> bool {
31+ fn is_write_locked ( state : Primitive ) -> bool {
3332 state & MASK == WRITE_LOCKED
3433}
3534
3635#[ inline]
37- fn has_readers_waiting ( state : u32 ) -> bool {
36+ fn has_readers_waiting ( state : Primitive ) -> bool {
3837 state & READERS_WAITING != 0
3938}
4039
4140#[ inline]
42- fn has_writers_waiting ( state : u32 ) -> bool {
41+ fn has_writers_waiting ( state : Primitive ) -> bool {
4342 state & WRITERS_WAITING != 0
4443}
4544
4645#[ inline]
47- fn is_read_lockable ( state : u32 ) -> bool {
46+ fn is_read_lockable ( state : Primitive ) -> bool {
4847 // This also returns false if the counter could overflow if we tried to read lock it.
4948 //
5049 // We don't allow read-locking if there's readers waiting, even if the lock is unlocked
@@ -55,14 +54,14 @@ fn is_read_lockable(state: u32) -> bool {
5554}
5655
5756#[ inline]
58- fn has_reached_max_readers ( state : u32 ) -> bool {
57+ fn has_reached_max_readers ( state : Primitive ) -> bool {
5958 state & MASK == MAX_READERS
6059}
6160
6261impl RwLock {
6362 #[ inline]
6463 pub const fn new ( ) -> Self {
65- Self { state : AtomicU32 :: new ( 0 ) , writer_notify : AtomicU32 :: new ( 0 ) }
64+ Self { state : Futex :: new ( 0 ) , writer_notify : Futex :: new ( 0 ) }
6665 }
6766
6867 #[ inline]
@@ -225,7 +224,7 @@ impl RwLock {
225224 /// If both are waiting, this will wake up only one writer, but will fall
226225 /// back to waking up readers if there was no writer to wake up.
227226 #[ cold]
228- fn wake_writer_or_readers ( & self , mut state : u32 ) {
227+ fn wake_writer_or_readers ( & self , mut state : Primitive ) {
229228 assert ! ( is_unlocked( state) ) ;
230229
231230 // The readers waiting bit might be turned on at any point now,
@@ -290,7 +289,7 @@ impl RwLock {
290289
291290 /// Spin for a while, but stop directly at the given condition.
292291 #[ inline]
293- fn spin_until ( & self , f : impl Fn ( u32 ) -> bool ) -> u32 {
292+ fn spin_until ( & self , f : impl Fn ( Primitive ) -> bool ) -> Primitive {
294293 let mut spin = 100 ; // Chosen by fair dice roll.
295294 loop {
296295 let state = self . state . load ( Relaxed ) ;
@@ -303,13 +302,13 @@ impl RwLock {
303302 }
304303
305304 #[ inline]
306- fn spin_write ( & self ) -> u32 {
305+ fn spin_write ( & self ) -> Primitive {
307306 // Stop spinning when it's unlocked or when there's waiting writers, to keep things somewhat fair.
308307 self . spin_until ( |state| is_unlocked ( state) || has_writers_waiting ( state) )
309308 }
310309
311310 #[ inline]
312- fn spin_read ( & self ) -> u32 {
311+ fn spin_read ( & self ) -> Primitive {
313312 // Stop spinning when it's unlocked or read locked, or when there's waiting threads.
314313 self . spin_until ( |state| {
315314 !is_write_locked ( state) || has_readers_waiting ( state) || has_writers_waiting ( state)
0 commit comments