@@ -45,6 +45,11 @@ fn writers_waiting(state: i32) -> bool {
4545
4646fn read_lockable ( state : i32 ) -> bool {
4747 // This also returns false if the counter could overflow if we tried to read lock it.
48+ //
49+ // We don't allow read-locking if there's readers waiting, even if the lock is unlocked
50+ // and there's no writers waiting. The only situation when this happens is after unlocking,
51+ // at which point the unlocking thread might be waking up writers, which have priority over readers.
52+ // The unlocking thread will clear the readers waiting bit and wake up readers, if necssary.
4853 state & MASK < MAX_READERS && !readers_waiting ( state) && !writers_waiting ( state)
4954}
5055
@@ -249,7 +254,8 @@ impl RwLock {
249254 if self . wake_writer ( ) {
250255 return ;
251256 }
252- // No writers were actually waiting. Continue to wake up readers instead.
257+ // No writers were actually blocked on futex_wait, so we continue
258+ // to wake up readers instead, since we can't be sure if we notified a writer.
253259 state = READERS_WAITING ;
254260 }
255261
@@ -261,6 +267,11 @@ impl RwLock {
261267 }
262268 }
263269
270+ /// This wakes one writer and returns true if we woke up a writer that was
271+ /// blocked on futex_wait.
272+ ///
273+ /// If this returns false, it might still be the case that we notified a
274+ /// writer that was about to go to sleep.
264275 fn wake_writer ( & self ) -> bool {
265276 self . writer_notify . fetch_add ( 1 , Release ) ;
266277 futex_wake ( & self . writer_notify )
0 commit comments