From b101b127f3797adc4d473ed23660e1953d31f7c8 Mon Sep 17 00:00:00 2001 From: David Xu Date: Fri, 25 Sep 2009 00:03:13 +0000 Subject: [PATCH] In function do_rw_wrlock, when a writer got an error and before returning, check if there are readers blocked by us via URWLOCK_WRITE_WAITERS flag, and resume the readers. The error must be EAGAIN, otherwise there must have memory problem, and nobody can rescue the buggy application. The revision 197445 might be reverted. --- sys/kern/kern_umtx.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c index bcb60edd8d14..2ab099d758fc 100644 --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -2556,6 +2556,7 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) uint32_t flags; int32_t state, oldstate; int32_t blocked_writers; + int32_t blocked_readers; int error; uq = td->td_umtxq; @@ -2564,6 +2565,7 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) if (error != 0) return (error); + blocked_readers = 0; for (;;) { state = fuword32(__DEVOLATILE(int32_t *, &rwlock->rw_state)); while (!(state & URWLOCK_WRITE_OWNER) && URWLOCK_READER_COUNT(state) == 0) { @@ -2575,8 +2577,18 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) state = oldstate; } - if (error) + if (error) { + if (!(state & (URWLOCK_WRITE_OWNER|URWLOCK_WRITE_WAITERS)) && + blocked_readers != 0) { + umtxq_lock(&uq->uq_key); + umtxq_busy(&uq->uq_key); + umtxq_signal_queue(&uq->uq_key, INT_MAX, UMTX_SHARED_QUEUE); + umtxq_unbusy(&uq->uq_key); + umtxq_unlock(&uq->uq_key); + } + break; + } /* grab monitor lock */ umtxq_lock(&uq->uq_key); @@ -2627,7 +2639,9 @@ do_rw_wrlock(struct thread *td, struct urwlock *rwlock, int timo) break; state = oldstate; } - } + blocked_readers = fuword32(&rwlock->rw_blocked_readers); + } else + blocked_readers = 0; umtxq_lock(&uq->uq_key); umtxq_unbusy(&uq->uq_key);