diff options
author | anton <anton@cvs.openbsd.org> | 2019-11-19 19:19:29 +0000 |
---|---|---|
committer | anton <anton@cvs.openbsd.org> | 2019-11-19 19:19:29 +0000 |
commit | a31f639de997636f9b80a35d3d08ad233b82f772 (patch) | |
tree | 471df74e409e5a6df0d9e1dcf92f6574fa1a305a /sys/kern | |
parent | 348dca9f8ad281f3f3809121fcac6d7934215173 (diff) |
When waiting on pipe I/O, simplify the unlock/relock logic using
rwsleep(). All made possible by the recent switch to using a rwlock as
the exclusive pipe lock.
ok visa@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/sys_pipe.c | 56 |
1 files changed, 36 insertions, 20 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 2a5f5613a5d..034d7937932 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_pipe.c,v 1.98 2019/11/11 16:45:46 anton Exp $ */ +/* $OpenBSD: sys_pipe.c,v 1.99 2019/11/19 19:19:28 anton Exp $ */ /* * Copyright (c) 1996 John S. Dyson @@ -106,6 +106,8 @@ void pipe_destroy(struct pipe *); int pipe_buffer_realloc(struct pipe *, u_int); void pipe_buffer_free(struct pipe *); +int pipe_sleep(struct pipe *, const char *); + /* * The pipe system call for the DTYPE_PIPE type of pipes */ @@ -287,6 +289,30 @@ pipeunlock(struct pipe *cpipe) rw_exit(&cpipe->pipe_lock); } +/* + * Unlock the given pipe and go to sleep. Returns 0 on success and the + * pipe is relocked. Otherwise if a signal was caught, non-zero is returned and + * the pipe is not locked. + * + * Any caller must obtain a reference to the pipe by incrementing `pipe_busy' + * before calling this function in order ensure that the same pipe is not + * destroyed while sleeping. + */ +int +pipe_sleep(struct pipe *cpipe, const char *wmesg) +{ + int error; + + rw_assert_wrlock(&cpipe->pipe_lock); + + error = rwsleep_nsec(cpipe, &cpipe->pipe_lock, + PRIBIO | PCATCH | PNORELOCK, wmesg, INFSLP); + if (error) + return (error); + + return (pipelock(cpipe)); +} + void pipeselwakeup(struct pipe *cpipe) { @@ -368,23 +394,18 @@ pipe_read(struct file *fp, struct uio *uio, int fflags) break; /* - * Unlock the pipe buffer for our remaining processing. - * We will either break out with an error or we will - * sleep and relock to loop. - */ - pipeunlock(rpipe); - - /* - * Handle non-blocking mode operation or - * wait for more data. + * Handle non-blocking mode operation. */ if (fp->f_flag & FNONBLOCK) { error = EAGAIN; - } else { - rpipe->pipe_state |= PIPE_WANTR; - if ((error = tsleep(rpipe, PRIBIO|PCATCH, "piperd", 0)) == 0) - error = pipelock(rpipe); + break; } + + /* + * Wait for more data. + */ + rpipe->pipe_state |= PIPE_WANTR; + error = pipe_sleep(rpipe, "piperd"); if (error) goto unlocked_error; } @@ -573,13 +594,8 @@ pipe_write(struct file *fp, struct uio *uio, int fflags) */ pipeselwakeup(wpipe); - pipeunlock(wpipe); wpipe->pipe_state |= PIPE_WANTW; - error = tsleep(wpipe, (PRIBIO + 1)|PCATCH, - "pipewr", 0); - if (error) - goto unlocked_error; - error = pipelock(wpipe); + error = pipe_sleep(wpipe, "pipewr"); if (error) goto unlocked_error; |