diff options
| author | Attilio Rao <attilio@FreeBSD.org> | 2009-10-13 13:03:31 +0000 |
|---|---|---|
| committer | Attilio Rao <attilio@FreeBSD.org> | 2009-10-13 13:03:31 +0000 |
| commit | be0ac1601505357fe1fe0ea3557438e6948cb404 (patch) | |
| tree | f7b195a5fe0de85358a8e315aa03b94d020a5b1c /sys/kern | |
| parent | aba70b5e590d2e3acce46a300640b75afc46c7ee (diff) | |
Notes
Diffstat (limited to 'sys/kern')
| -rw-r--r-- | sys/kern/kern_umtx.c | 18 |
1 files 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 @@ sleep: break; state = oldstate; } - } + blocked_readers = fuword32(&rwlock->rw_blocked_readers); + } else + blocked_readers = 0; umtxq_lock(&uq->uq_key); umtxq_unbusy(&uq->uq_key); |
