From 676e6574a1bd15c8261cba8e86714e8199db2054 Mon Sep 17 00:00:00 2001 From: David Xu Date: Wed, 3 Feb 2010 03:56:32 +0000 Subject: [PATCH] After busied the lock, re-read state word before checking waiters flag, otherwise, the waiters bit may not be set and a wakeup is lost. Submitted by: justin.teller at gmail dot com MFC after: 3 days --- sys/kern/kern_umtx.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index 71287c4ba6fc..135f7c76afa6 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -2526,6 +2526,12 @@ do_rw_rdlock(struct thread *td, struct urwlock *rwlock, long fflag, int timo) umtxq_busy(&uq->uq_key); umtxq_unlock(&uq->uq_key); + /* + * re-read the state, in case it changed between the try-lock above + * and the check below + */ + state = fuword32(__DEVOLATILE(int32_t *, &rwlock->rw_state)); + /* set read contention bit */ while ((state & wrflags) && !(state & URWLOCK_READ_WAITERS)) { oldstate = casuword32(&rwlock->rw_state, state, state | URWLOCK_READ_WAITERS); @@ -2658,6 +2664,12 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) umtxq_busy(&uq->uq_key); umtxq_unlock(&uq->uq_key); + /* + * re-read the state, in case it changed between the try-lock above + * and the check below + */ + state = fuword32(__DEVOLATILE(int32_t *, &rwlock->rw_state)); + while (((state & URWLOCK_WRITE_OWNER) || URWLOCK_READER_COUNT(state) != 0) && (state & URWLOCK_WRITE_WAITERS) == 0) { oldstate = casuword32(&rwlock->rw_state, state, state | URWLOCK_WRITE_WAITERS);