@@ -479,31 +479,43 @@ impl RwLock {
479479 "RwLock should be LOCKED and QUEUED"
480480 ) ;
481481
482+ // 1. Attempt to grab the queue lock
483+ // 2. Find the tail of the queue
484+ // 3. While the current tail is not a writer:
485+ // 4. The current tail must be a reader
486+ // 5. Remove the current tail from the queue and update the tail to be the previous
487+ // node if possible
488+ // 6. Set the flag (somewhere on the node) to notify the reader thread that it has
489+ // been woken up by a `downgrade` call
490+ // 7. `complete` the node
491+ // 8. Go back to step 3 with the updated tail if it exists, otherwise break
492+ // 9. Once we find a writer or there are no more `prev` links, we write the correct
493+ // number of readers into the current node state or the head state.
494+
495+ // 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,
510+ }
511+ }
512+
482513 // FIXME Is this correct?
483514 // SAFETY: Since we have the write lock, nobody else can be modifying state, and since
484515 // we got `state` from the `compare_exchange`, we know it is a valid head of the queue.
485516 let tail = unsafe { add_backlinks_and_find_tail ( to_node ( state) ) } ;
486517
487- // FIXME Is this safe to modify? There shouldn't be other threads modifying this since
488- // we have the write lock and only we should be able to modify the nodes in the queue...
489- // Increment the reader count from 0 to 1.
490- let old = unsafe { tail. as_ref ( ) } . next . 0 . fetch_byte_add ( SINGLE , AcqRel ) . addr ( ) ;
491- debug_assert_eq ! ( old, 0 , "Reader count was not zero while we had the write lock" ) ;
492-
493- // Now that we are in read mode, traverse the queue and wake up readers until we find a
494- // writer node.
495- let mut current = tail;
496- while unsafe { !current. as_ref ( ) . write } {
497- let prev = unsafe { current. as_ref ( ) . prev . get ( ) } ;
498- unsafe {
499- // There must be threads waiting.
500- Node :: complete ( current) ;
501- }
502- match prev {
503- Some ( prev) => current = prev,
504- None => return ,
505- }
506- }
518+ todo ! ( )
507519 }
508520 }
509521
0 commit comments