@@ -468,7 +468,7 @@ impl RwLock {
468
468
pub unsafe fn downgrade ( & self ) {
469
469
// Atomically attempt to go from a single writer without any waiting threads to a single
470
470
// reader without any waiting threads.
471
- if let Err ( state) = self . state . compare_exchange (
471
+ if let Err ( mut state) = self . state . compare_exchange (
472
472
without_provenance_mut ( LOCKED ) ,
473
473
without_provenance_mut ( LOCKED | SINGLE ) ,
474
474
Release ,
@@ -478,7 +478,6 @@ impl RwLock {
478
478
state. mask( LOCKED ) . addr( ) != 0 && state. mask( QUEUED ) . addr( ) != 0 ,
479
479
"RwLock should be LOCKED and QUEUED"
480
480
) ;
481
-
482
481
// 1. Attempt to grab the queue lock
483
482
// 2. Find the tail of the queue
484
483
// 3. While the current tail is not a writer:
@@ -493,29 +492,31 @@ impl RwLock {
493
492
// number of readers into the current node state or the head state.
494
493
495
494
// Attempt to grab the queue lock.
496
- loop {
497
- // Atomically release the lock and try to acquire the queue lock.
498
- let next = state. map_addr ( |addr| addr | QUEUE_LOCKED ) ;
499
- match self . state . compare_exchange_weak ( state & !QUEUE_LOCKED , next, AcqRel , Relaxed )
500
- {
501
- // The queue lock was acquired. Release it, waking up the next
502
- // waiter in the process.
503
- Ok ( _) if state. addr ( ) & QUEUE_LOCKED == 0 => unsafe {
504
- return self . unlock_queue ( next) ;
505
- } ,
506
- // Another thread already holds the queue lock, leave waking up
507
- // waiters to it.
508
- Ok ( _) => return ,
509
- Err ( new) => state = new,
495
+ state = loop {
496
+ match self . state . fetch_update ( Release , Acquire , |ptr : State | {
497
+ // Go from not queue locked to being queue locked.
498
+ if ptr. mask ( QUEUE_LOCKED ) . addr ( ) != 0 {
499
+ Some ( without_provenance_mut ( ptr. addr ( ) | QUEUE_LOCKED ) )
500
+ } else {
501
+ None
502
+ }
503
+ } ) {
504
+ Ok ( state) => break state,
505
+ Err ( _) => { }
510
506
}
511
- }
507
+ } ;
508
+
509
+ // SAFETY: FIXME
510
+ let _head = unsafe { to_node ( state) . as_ref ( ) } ;
512
511
513
512
// FIXME Is this correct?
514
513
// SAFETY: Since we have the write lock, nobody else can be modifying state, and since
515
514
// we got `state` from the `compare_exchange`, we know it is a valid head of the queue.
516
- let tail = unsafe { add_backlinks_and_find_tail ( to_node ( state) ) } ;
515
+ let tail = unsafe { add_backlinks_and_find_tail ( to_node ( state) ) . as_ref ( ) } ;
517
516
518
- todo ! ( )
517
+ while !tail. write {
518
+ todo ! ( )
519
+ }
519
520
}
520
521
}
521
522
0 commit comments