@@ -468,7 +468,7 @@ impl RwLock {
468468 pub unsafe fn downgrade ( & self ) {
469469 // Atomically attempt to go from a single writer without any waiting threads to a single
470470 // reader without any waiting threads.
471- if let Err ( state) = self . state . compare_exchange (
471+ if let Err ( mut state) = self . state . compare_exchange (
472472 without_provenance_mut ( LOCKED ) ,
473473 without_provenance_mut ( LOCKED | SINGLE ) ,
474474 Release ,
@@ -478,7 +478,6 @@ impl RwLock {
478478 state. mask( LOCKED ) . addr( ) != 0 && state. mask( QUEUED ) . addr( ) != 0 ,
479479 "RwLock should be LOCKED and QUEUED"
480480 ) ;
481-
482481 // 1. Attempt to grab the queue lock
483482 // 2. Find the tail of the queue
484483 // 3. While the current tail is not a writer:
@@ -493,29 +492,31 @@ impl RwLock {
493492 // number of readers into the current node state or the head state.
494493
495494 // 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 ( _) => { }
510506 }
511- }
507+ } ;
508+
509+ // SAFETY: FIXME
510+ let _head = unsafe { to_node ( state) . as_ref ( ) } ;
512511
513512 // FIXME Is this correct?
514513 // SAFETY: Since we have the write lock, nobody else can be modifying state, and since
515514 // 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 ( ) } ;
517516
518- todo ! ( )
517+ while !tail. write {
518+ todo ! ( )
519+ }
519520 }
520521 }
521522
0 commit comments