pipe: thundering herd problem in pipelock
All reads and writes are serialized with a hand-rolled lock, but unlocking it always wakes up all waiters. Existing flag fields get resized to make room for introduction of waiter counter without growing the struct. Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D27273
This commit is contained in:
parent
7e9e52e7a7
commit
f9fe7b28bc
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=367852
@ -622,9 +622,13 @@ pipelock(struct pipe *cpipe, int catch)
|
||||
if (catch)
|
||||
prio |= PCATCH;
|
||||
while (cpipe->pipe_state & PIPE_LOCKFL) {
|
||||
cpipe->pipe_state |= PIPE_LWANT;
|
||||
KASSERT(cpipe->pipe_waiters >= 0,
|
||||
("%s: bad waiter count %d", __func__,
|
||||
cpipe->pipe_waiters));
|
||||
cpipe->pipe_waiters++;
|
||||
error = msleep(cpipe, PIPE_MTX(cpipe),
|
||||
prio, "pipelk", 0);
|
||||
cpipe->pipe_waiters--;
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
@ -642,10 +646,12 @@ pipeunlock(struct pipe *cpipe)
|
||||
PIPE_LOCK_ASSERT(cpipe, MA_OWNED);
|
||||
KASSERT(cpipe->pipe_state & PIPE_LOCKFL,
|
||||
("Unlocked pipe passed to pipeunlock"));
|
||||
KASSERT(cpipe->pipe_waiters >= 0,
|
||||
("%s: bad waiter count %d", __func__,
|
||||
cpipe->pipe_waiters));
|
||||
cpipe->pipe_state &= ~PIPE_LOCKFL;
|
||||
if (cpipe->pipe_state & PIPE_LWANT) {
|
||||
cpipe->pipe_state &= ~PIPE_LWANT;
|
||||
wakeup(cpipe);
|
||||
if (cpipe->pipe_waiters > 0) {
|
||||
wakeup_one(cpipe);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,9 +116,10 @@ struct pipe {
|
||||
struct pipe *pipe_peer; /* link with other direction */
|
||||
struct pipepair *pipe_pair; /* container structure pointer */
|
||||
u_short pipe_state; /* pipe status info */
|
||||
u_short pipe_type; /* pipe type info */
|
||||
u_char pipe_type; /* pipe type info */
|
||||
u_char pipe_present; /* still present? */
|
||||
int pipe_waiters; /* pipelock waiters */
|
||||
int pipe_busy; /* busy flag, mostly to handle rundown sanely */
|
||||
int pipe_present; /* still present? */
|
||||
int pipe_wgen; /* writer generation for named pipe */
|
||||
ino_t pipe_ino; /* fake inode for stat(2) */
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user