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