summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_umtx.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2009-09-25 00:03:13 +0000
committerdavidxu <davidxu@FreeBSD.org>2009-09-25 00:03:13 +0000
commit14cbd7c194c8b2d03562e97e659e4bd3b971fbb9 (patch)
treeb5a60da749251c2ededcb8d568c6d5fafd1c0605 /sys/kern/kern_umtx.c
parent21b9526006ca4901db3a8aa71d2b81dcdb1856ff (diff)
downloadFreeBSD-src-14cbd7c194c8b2d03562e97e659e4bd3b971fbb9.zip
FreeBSD-src-14cbd7c194c8b2d03562e97e659e4bd3b971fbb9.tar.gz
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.
Diffstat (limited to 'sys/kern/kern_umtx.c')
-rw-r--r--sys/kern/kern_umtx.c18
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);
OpenPOWER on IntegriCloud