@@ -45,6 +45,11 @@ fn writers_waiting(state: i32) -> bool {
45
45
46
46
fn read_lockable ( state : i32 ) -> bool {
47
47
// 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.
48
53
state & MASK < MAX_READERS && !readers_waiting ( state) && !writers_waiting ( state)
49
54
}
50
55
@@ -249,7 +254,8 @@ impl RwLock {
249
254
if self . wake_writer ( ) {
250
255
return ;
251
256
}
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.
253
259
state = READERS_WAITING ;
254
260
}
255
261
@@ -261,6 +267,11 @@ impl RwLock {
261
267
}
262
268
}
263
269
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.
264
275
fn wake_writer ( & self ) -> bool {
265
276
self . writer_notify . fetch_add ( 1 , Release ) ;
266
277
futex_wake ( & self . writer_notify )
0 commit comments