diff options
author | des <des@FreeBSD.org> | 2009-09-25 22:45:59 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2009-09-25 22:45:59 +0000 |
commit | bf5117185e83a178d672946c3f7053d0ef92be27 (patch) | |
tree | 394fcfe01b613c0b5b5edbfc414a17c73481ad5d /sys/kern/kern_umtx.c | |
parent | b79ff8160af6fa640e29ce784e59acd49cd1e7fc (diff) | |
parent | 5c2742e3dae3ef549329b770ec44b16ca930dc1f (diff) | |
download | FreeBSD-src-bf5117185e83a178d672946c3f7053d0ef92be27.zip FreeBSD-src-bf5117185e83a178d672946c3f7053d0ef92be27.tar.gz |
Sync with head
Diffstat (limited to 'sys/kern/kern_umtx.c')
-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 bcb60ed..2ab099d 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); |