tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
thundering pipe herds
mjg at freebsd says that their pipes have a thundering herd problem
that manifests in make's token pipe stuff at high -j values. We have
the same logic, and it's easily fixed.
Completely untested patch follows; does anyone object to this assuming
that it works (possibly after minor changes)?
(pipe_waiters is inserted where it is so it occupies what's currently
struct padding on 64-bit machines)
Index: sys/pipe.h
===================================================================
RCS file: /cvsroot/src/sys/sys/pipe.h,v
retrieving revision 1.36
diff -u -p -r1.36 pipe.h
--- sys/pipe.h 22 Aug 2018 01:05:24 -0000 1.36
+++ sys/pipe.h 23 Nov 2020 21:23:07 -0000
@@ -93,8 +93,7 @@ struct pipemapping {
#define PIPE_DIRECTR 0x080 /* Pipe direct read request (setup complete) */
#define PIPE_LOCKFL 0x100 /* Process has exclusive access to
pointers/data. */
-#define PIPE_LWANT 0x200 /* Process wants exclusive access to
- pointers/data. */
+/* unused 0x200 */
#define PIPE_RESTART 0x400 /* Return ERESTART to blocked syscalls */
/*
@@ -114,6 +113,7 @@ struct pipe {
struct timespec pipe_mtime; /* time of last modify */
struct timespec pipe_btime; /* time of creation */
pid_t pipe_pgid; /* process group for sigio */
+ u_int pipe_waiters; /* number of waiters pending */
struct pipe *pipe_peer; /* link with other direction */
u_int pipe_state; /* pipe status info */
int pipe_busy; /* busy flag, to handle rundown */
Index: kern/sys_pipe.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_pipe.c,v
retrieving revision 1.148
diff -u -p -r1.148 sys_pipe.c
--- kern/sys_pipe.c 26 Apr 2019 17:24:23 -0000 1.148
+++ kern/sys_pipe.c 23 Nov 2020 21:23:07 -0000
@@ -371,13 +371,19 @@ pipelock(struct pipe *pipe, bool catch_p
KASSERT(mutex_owned(pipe->pipe_lock));
while (pipe->pipe_state & PIPE_LOCKFL) {
- pipe->pipe_state |= PIPE_LWANT;
+ pipe->pipe_waiters++;
+ KASSERT(pipe->pipe_waiters != 0); /* just in case */
if (catch_p) {
error = cv_wait_sig(&pipe->pipe_lkcv, pipe->pipe_lock);
- if (error != 0)
+ if (error != 0) {
+ KASSERT(pipe->pipe_waiters > 0);
+ pipe->pipe_waiters--;
return error;
+ }
} else
cv_wait(&pipe->pipe_lkcv, pipe->pipe_lock);
+ KASSERT(pipe->pipe_waiters > 0);
+ pipe->pipe_waiters--;
}
pipe->pipe_state |= PIPE_LOCKFL;
@@ -395,9 +401,8 @@ pipeunlock(struct pipe *pipe)
KASSERT(pipe->pipe_state & PIPE_LOCKFL);
pipe->pipe_state &= ~PIPE_LOCKFL;
- if (pipe->pipe_state & PIPE_LWANT) {
- pipe->pipe_state &= ~PIPE_LWANT;
- cv_broadcast(&pipe->pipe_lkcv);
+ if (pipe->pipe_waiters > 0) {
+ cv_signal(&pipe->pipe_lkcv);
}
}
--
David A. Holland
dholland%netbsd.org@localhost
Home |
Main Index |
Thread Index |
Old Index