Index: sys/kern/sys_pipe.c =================================================================== --- sys/kern/sys_pipe.c +++ sys/kern/sys_pipe.c @@ -721,6 +721,30 @@ 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 && +#ifdef __ILP32__ + atomic_load_int(&rpipe->pipe_pages.cnt) == 0) +#else + atomic_load_long(&rpipe->pipe_pages.cnt) == 0) +#endif + return (EAGAIN); + } + PIPE_LOCK(rpipe); ++rpipe->pipe_busy; error = pipelock(rpipe, 1); Index: sys/security/mac/mac_framework.h =================================================================== --- sys/security/mac/mac_framework.h +++ sys/security/mac/mac_framework.h @@ -271,7 +271,22 @@ #endif #define mac_pipe_check_stat_enabled() __predict_false(mac_pipe_check_stat_fp_flag) int mac_pipe_check_stat(struct ucred *cred, struct pipepair *pp); -int mac_pipe_check_read(struct ucred *cred, struct pipepair *pp); +int mac_pipe_check_read_impl(struct ucred *cred, struct pipepair *pp); +#ifdef MAC +extern bool mac_pipe_check_read_fp_flag; +#else +#define mac_pipe_check_read_fp_flag false +#endif +#define mac_pipe_check_read_enabled() __predict_false(mac_pipe_check_read_fp_flag) +static inline int +mac_pipe_check_read(struct ucred *cred, struct pipepair *pp) +{ + + if (mac_pipe_check_read_enabled()) + return (mac_pipe_check_read_impl(cred, pp)); + return (0); +} + int mac_pipe_check_write(struct ucred *cred, struct pipepair *pp); void mac_pipe_create(struct ucred *cred, struct pipepair *pp); void mac_pipe_destroy(struct pipepair *); Index: sys/security/mac/mac_framework.c =================================================================== --- sys/security/mac/mac_framework.c +++ sys/security/mac/mac_framework.c @@ -145,6 +145,7 @@ FPFLAG_RARE(vnode_check_readlink); FPFLAG_RARE(pipe_check_stat); FPFLAG_RARE(pipe_check_poll); +FPFLAG_RARE(pipe_check_read); FPFLAG_RARE(ifnet_create_mbuf); FPFLAG_RARE(ifnet_check_transmit); @@ -447,6 +448,8 @@ .flag = &mac_pipe_check_stat_fp_flag }, { .offset = FPO(pipe_check_poll), .flag = &mac_pipe_check_poll_fp_flag }, + { .offset = FPO(pipe_check_read), + .flag = &mac_pipe_check_read_fp_flag }, { .offset = FPO(ifnet_create_mbuf), .flag = &mac_ifnet_create_mbuf_fp_flag }, { .offset = FPO(ifnet_check_transmit), Index: sys/security/mac/mac_pipe.c =================================================================== --- sys/security/mac/mac_pipe.c +++ sys/security/mac/mac_pipe.c @@ -179,7 +179,7 @@ "struct pipepair *"); int -mac_pipe_check_read(struct ucred *cred, struct pipepair *pp) +mac_pipe_check_read_impl(struct ucred *cred, struct pipepair *pp) { int error;