@@ -479,31 +479,43 @@ impl RwLock {
479
479
"RwLock should be LOCKED and QUEUED"
480
480
) ;
481
481
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
+
482
513
// FIXME Is this correct?
483
514
// SAFETY: Since we have the write lock, nobody else can be modifying state, and since
484
515
// we got `state` from the `compare_exchange`, we know it is a valid head of the queue.
485
516
let tail = unsafe { add_backlinks_and_find_tail ( to_node ( state) ) } ;
486
517
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 ! ( )
507
519
}
508
520
}
509
521
0 commit comments