summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2018-08-13 14:35:30 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2018-08-13 14:35:30 +0000
commit02dc1e8680f7bb858d97db9652c373f10a7b10d6 (patch)
tree9e991a38e147074f03ba81bfbde15cc174c363f2 /sys/kern
parente619ad16f97500db739ba0b349bf488bd702d70d (diff)
Make it possible to run pipe(2) and pipe2(2) mostly w/o KERNEL_LOCK():
- Update counters atomatically - Use IPL_MPFLOOR for pipe's pool. - Grab the KERNEL_LOCK() before calling km_alloc(9) & km_free(9) Inputs from kettenis@, ok visa@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/sys_pipe.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index f3cf0fa382c..d9c68a30535 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sys_pipe.c,v 1.82 2018/07/10 08:58:50 mpi Exp $ */
+/* $OpenBSD: sys_pipe.c,v 1.83 2018/08/13 14:35:29 mpi Exp $ */
/*
* Copyright (c) 1996 John S. Dyson
@@ -91,8 +91,8 @@ struct filterops pipe_wfiltops =
* Limit the number of "big" pipes
*/
#define LIMITBIGPIPES 32
-int nbigpipe;
-static int amountpipekva;
+unsigned int nbigpipe;
+static unsigned int amountpipekva;
struct pool pipe_pool;
@@ -214,7 +214,9 @@ pipespace(struct pipe *cpipe, u_int size)
{
caddr_t buffer;
+ KERNEL_LOCK();
buffer = km_alloc(size, &kv_any, &kp_pageable, &kd_waitok);
+ KERNEL_UNLOCK();
if (buffer == NULL) {
return (ENOMEM);
}
@@ -227,7 +229,7 @@ pipespace(struct pipe *cpipe, u_int size)
cpipe->pipe_buffer.out = 0;
cpipe->pipe_buffer.cnt = 0;
- amountpipekva += cpipe->pipe_buffer.size;
+ atomic_add_int(&amountpipekva, cpipe->pipe_buffer.size);
return (0);
}
@@ -444,15 +446,18 @@ pipe_write(struct file *fp, off_t *poff, struct uio *uio, struct ucred *cred)
* so.
*/
if ((uio->uio_resid > PIPE_SIZE) &&
- (nbigpipe < LIMITBIGPIPES) &&
(wpipe->pipe_buffer.size <= PIPE_SIZE) &&
(wpipe->pipe_buffer.cnt == 0)) {
+ unsigned int npipe;
- if ((error = pipelock(wpipe)) == 0) {
- if (pipespace(wpipe, BIG_PIPE_SIZE) == 0)
- nbigpipe++;
+ npipe = atomic_inc_int_nv(&nbigpipe);
+ if ((npipe <= LIMITBIGPIPES) &&
+ (error = pipelock(wpipe)) == 0) {
+ if (pipespace(wpipe, BIG_PIPE_SIZE) != 0)
+ atomic_dec_int(&nbigpipe);
pipeunlock(wpipe);
- }
+ } else
+ atomic_dec_int(&nbigpipe);
}
/*
@@ -759,13 +764,16 @@ pipe_close(struct file *fp, struct proc *p)
void
pipe_free_kmem(struct pipe *cpipe)
{
+ u_int size = cpipe->pipe_buffer.size;
+
if (cpipe->pipe_buffer.buffer != NULL) {
- if (cpipe->pipe_buffer.size > PIPE_SIZE)
- --nbigpipe;
- amountpipekva -= cpipe->pipe_buffer.size;
- km_free(cpipe->pipe_buffer.buffer, cpipe->pipe_buffer.size,
- &kv_any, &kp_pageable);
+ KERNEL_LOCK();
+ km_free(cpipe->pipe_buffer.buffer, size, &kv_any, &kp_pageable);
+ KERNEL_UNLOCK();
+ atomic_sub_int(&amountpipekva, size);
cpipe->pipe_buffer.buffer = NULL;
+ if (size > PIPE_SIZE)
+ atomic_dec_int(&nbigpipe);
}
}
@@ -777,7 +785,6 @@ pipeclose(struct pipe *cpipe)
{
struct pipe *ppipe;
if (cpipe) {
-
pipeselwakeup(cpipe);
/*
@@ -889,7 +896,7 @@ filt_pipewrite(struct knote *kn, long hint)
void
pipe_init(void)
{
- pool_init(&pipe_pool, sizeof(struct pipe), 0, IPL_NONE, PR_WAITOK,
+ pool_init(&pipe_pool, sizeof(struct pipe), 0, IPL_MPFLOOR, PR_WAITOK,
"pipepl", NULL);
}