git: 9ac6eda6c6a3 - main - pipe: try to skip locking the pipe if a non-blocking fd is used
Date: Wed, 17 Aug 2022 14:23:51 UTC
The branch main has been updated by mjg:
URL: https://cgit.FreeBSD.org/src/commit/?id=9ac6eda6c6a36db6bffa01be7faea24f8bb92a0f
commit 9ac6eda6c6a36db6bffa01be7faea24f8bb92a0f
Author: Mateusz Guzik <mjg@FreeBSD.org>
AuthorDate: 2022-08-08 18:02:15 +0000
Commit: Mateusz Guzik <mjg@FreeBSD.org>
CommitDate: 2022-08-17 14:23:34 +0000
pipe: try to skip locking the pipe if a non-blocking fd is used
Reviewed by: markj (previous version)
Differential Revision: https://reviews.freebsd.org/D36082
---
sys/kern/sys_pipe.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index d9e7d97d01e1..f9060ba2c8a6 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -721,6 +721,26 @@ pipe_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
int size;
rpipe = fp->f_data;
+
+ /*
+ * Try to avoid locking the pipe if we have nothing to do.
+ *
+ * There are programs which share one pipe amongst multiple processes
+ * and perform non-blocking reads in parallel, even if the pipe is
+ * empty. This in particular is the case with BSD make, which when
+ * spawned with a high -j number can find itself with over half of the
+ * calls failing to find anything.
+ */
+ if ((fp->f_flag & FNONBLOCK) != 0 && !mac_pipe_check_read_enabled()) {
+ if (__predict_false(uio->uio_resid == 0))
+ return (0);
+ if ((atomic_load_short(&rpipe->pipe_state) & PIPE_EOF) != 0)
+ return (0);
+ if (atomic_load_int(&rpipe->pipe_buffer.cnt) == 0 &&
+ atomic_load_int(&rpipe->pipe_pages.cnt) == 0)
+ return (EAGAIN);
+ }
+
PIPE_LOCK(rpipe);
++rpipe->pipe_busy;
error = pipelock(rpipe, 1);