1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-15 10:17:20 +00:00

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.
This commit is contained in:
David Xu 2009-09-25 00:03:13 +00:00
parent 5ec510d8f4
commit b101b127f3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=197476

View File

@ -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);