ksiginfo_t support.

This commit is contained in:
christos 2003-09-14 23:47:09 +00:00
parent cc39a7a050
commit e8ae1a44db
1 changed files with 58 additions and 24 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_pipe.c,v 1.41 2003/08/11 10:24:41 pk Exp $ */ /* $NetBSD: sys_pipe.c,v 1.42 2003/09/14 23:47:09 christos Exp $ */
/*- /*-
* Copyright (c) 2003 The NetBSD Foundation, Inc. * Copyright (c) 2003 The NetBSD Foundation, Inc.
@ -83,7 +83,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_pipe.c,v 1.41 2003/08/11 10:24:41 pk Exp $"); __KERNEL_RCSID(0, "$NetBSD: sys_pipe.c,v 1.42 2003/09/14 23:47:09 christos Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -184,14 +184,16 @@ static int amountpipekva = 0;
MALLOC_DEFINE(M_PIPE, "pipe", "Pipe structures"); MALLOC_DEFINE(M_PIPE, "pipe", "Pipe structures");
static void pipeclose(struct pipe *pipe); static void pipeclose(struct file *fp, struct pipe *pipe);
static void pipe_free_kmem(struct pipe *pipe); static void pipe_free_kmem(struct pipe *pipe);
static int pipe_create(struct pipe **pipep, int allockva); static int pipe_create(struct pipe **pipep, int allockva);
static int pipelock(struct pipe *pipe, int catch); static int pipelock(struct pipe *pipe, int catch);
static __inline void pipeunlock(struct pipe *pipe); static __inline void pipeunlock(struct pipe *pipe);
static void pipeselwakeup(struct pipe *pipe, struct pipe *sigp); static void pipeselwakeup(struct pipe *pipe, struct pipe *sigp, void *data,
int code);
#ifndef PIPE_NODIRECT #ifndef PIPE_NODIRECT
static int pipe_direct_write(struct pipe *wpipe, struct uio *uio); static int pipe_direct_write(struct file *fp, struct pipe *wpipe,
struct uio *uio);
#endif #endif
static int pipespace(struct pipe *pipe, int size); static int pipespace(struct pipe *pipe, int size);
@ -221,8 +223,8 @@ sys_pipe(l, v, retval)
p = l->l_proc; p = l->l_proc;
rpipe = wpipe = NULL; rpipe = wpipe = NULL;
if (pipe_create(&rpipe, 1) || pipe_create(&wpipe, 0)) { if (pipe_create(&rpipe, 1) || pipe_create(&wpipe, 0)) {
pipeclose(rpipe); pipeclose(NULL, rpipe);
pipeclose(wpipe); pipeclose(NULL, wpipe);
return (ENFILE); return (ENFILE);
} }
@ -265,8 +267,8 @@ free3:
ffree(rf); ffree(rf);
fdremove(p->p_fd, retval[0]); fdremove(p->p_fd, retval[0]);
free2: free2:
pipeclose(wpipe); pipeclose(NULL, wpipe);
pipeclose(rpipe); pipeclose(NULL, rpipe);
return (error); return (error);
} }
@ -396,11 +398,14 @@ pipeunlock(pipe)
* 'sigpipe' side of pipe. * 'sigpipe' side of pipe.
*/ */
static void static void
pipeselwakeup(selp, sigp) pipeselwakeup(selp, sigp, data, code)
struct pipe *selp, *sigp; struct pipe *selp, *sigp;
void *data;
int code;
{ {
struct proc *p; struct proc *p;
pid_t pid; pid_t pid;
ksiginfo_t ksi;
selnotify(&selp->pipe_sel, 0); selnotify(&selp->pipe_sel, 0);
if (sigp == NULL || (sigp->pipe_state & PIPE_ASYNC) == 0) if (sigp == NULL || (sigp->pipe_state & PIPE_ASYNC) == 0)
@ -410,10 +415,33 @@ pipeselwakeup(selp, sigp)
if (pid == 0) if (pid == 0)
return; return;
(void)memset(&ksi, 0, sizeof(ksi));
ksi.ksi_signo = SIGIO;
switch (ksi.ksi_code = code) {
case POLL_IN:
ksi.ksi_band = POLLIN|POLLRDNORM;
break;
case POLL_OUT:
ksi.ksi_band = POLLOUT|POLLWRNORM;
break;
case POLL_HUP:
ksi.ksi_band = POLLHUP;
break;
#if POLL_HUP != POLL_ERR
case POLL_ERR:
ksi.ksi_band = POLLERR;
break;
#endif
default:
#ifdef DIAGNOSTIC
printf("bad siginfo code %d in pipe notification.\n", code);
#endif
break;
}
if (pid > 0) if (pid > 0)
gsignal(pid, SIGIO); kgsignal(pid, &ksi, data);
else if ((p = pfind(-pid)) != NULL) else if ((p = pfind(-pid)) != NULL)
psignal(p, SIGIO); kpsignal(p, &ksi, data);
} }
/* ARGSUSED */ /* ARGSUSED */
@ -545,7 +573,8 @@ again:
/* /*
* We want to read more, wake up select/poll. * We want to read more, wake up select/poll.
*/ */
pipeselwakeup(rpipe, rpipe->pipe_peer); pipeselwakeup(rpipe, rpipe->pipe_peer, fp->f_data,
POLL_IN);
/* /*
* If the "write-side" is blocked, wake it up now. * If the "write-side" is blocked, wake it up now.
@ -597,7 +626,7 @@ unlocked_error:
*/ */
if ((bp->size - bp->cnt) >= PIPE_BUF if ((bp->size - bp->cnt) >= PIPE_BUF
&& (ocnt != bp->cnt || (rpipe->pipe_state & PIPE_SIGNALR))) { && (ocnt != bp->cnt || (rpipe->pipe_state & PIPE_SIGNALR))) {
pipeselwakeup(rpipe, rpipe->pipe_peer); pipeselwakeup(rpipe, rpipe->pipe_peer, fp->f_data, POLL_OUT);
rpipe->pipe_state &= ~PIPE_SIGNALR; rpipe->pipe_state &= ~PIPE_SIGNALR;
} }
@ -656,7 +685,8 @@ pipe_loan_free(wpipe)
* Called with the long-term pipe lock held. * Called with the long-term pipe lock held.
*/ */
static int static int
pipe_direct_write(wpipe, uio) pipe_direct_write(fp, wpipe, uio)
struct file *fp;
struct pipe *wpipe; struct pipe *wpipe;
struct uio *uio; struct uio *uio;
{ {
@ -753,7 +783,7 @@ pipe_direct_write(wpipe, uio)
wpipe->pipe_state &= ~PIPE_WANTR; wpipe->pipe_state &= ~PIPE_WANTR;
wakeup(wpipe); wakeup(wpipe);
} }
pipeselwakeup(wpipe, wpipe); pipeselwakeup(wpipe, wpipe, fp->f_data, POLL_IN);
error = ltsleep(wpipe, PRIBIO | PCATCH, "pipdwt", 0, error = ltsleep(wpipe, PRIBIO | PCATCH, "pipdwt", 0,
&wpipe->pipe_slock); &wpipe->pipe_slock);
if (error == 0 && wpipe->pipe_state & PIPE_EOF) if (error == 0 && wpipe->pipe_state & PIPE_EOF)
@ -773,7 +803,7 @@ pipe_direct_write(wpipe, uio)
pipe_loan_free(wpipe); pipe_loan_free(wpipe);
if (error) { if (error) {
pipeselwakeup(wpipe, wpipe); pipeselwakeup(wpipe, wpipe, fp->f_data, POLL_ERR);
/* /*
* If nothing was read from what we offered, return error * If nothing was read from what we offered, return error
@ -913,7 +943,7 @@ retry:
if ((uio->uio_iov->iov_len >= PIPE_MINDIRECT) && if ((uio->uio_iov->iov_len >= PIPE_MINDIRECT) &&
(fp->f_flag & FNONBLOCK) == 0 && (fp->f_flag & FNONBLOCK) == 0 &&
(wpipe->pipe_map.kva || (amountpipekva < limitpipekva))) { (wpipe->pipe_map.kva || (amountpipekva < limitpipekva))) {
error = pipe_direct_write(wpipe, uio); error = pipe_direct_write(fp, wpipe, uio);
/* /*
* Break out if error occured, unless it's ENOMEM. * Break out if error occured, unless it's ENOMEM.
@ -1017,7 +1047,8 @@ retry:
* wake up select/poll. * wake up select/poll.
*/ */
if (bp->cnt) if (bp->cnt)
pipeselwakeup(wpipe, wpipe); pipeselwakeup(wpipe, wpipe, fp->f_data,
POLL_OUT);
PIPE_LOCK(wpipe); PIPE_LOCK(wpipe);
pipeunlock(wpipe); pipeunlock(wpipe);
@ -1069,7 +1100,7 @@ retry:
* is only done synchronously), so check only wpipe->pipe_buffer.cnt * is only done synchronously), so check only wpipe->pipe_buffer.cnt
*/ */
if (bp->cnt) if (bp->cnt)
pipeselwakeup(wpipe, wpipe); pipeselwakeup(wpipe, wpipe, fp->f_data, POLL_OUT);
/* /*
* Arrange for next read(2) to do a signal. * Arrange for next read(2) to do a signal.
@ -1233,7 +1264,7 @@ pipe_close(fp, td)
struct pipe *pipe = (struct pipe *)fp->f_data; struct pipe *pipe = (struct pipe *)fp->f_data;
fp->f_data = NULL; fp->f_data = NULL;
pipeclose(pipe); pipeclose(fp, pipe);
return (0); return (0);
} }
@ -1266,7 +1297,8 @@ pipe_free_kmem(pipe)
* shutdown the pipe * shutdown the pipe
*/ */
static void static void
pipeclose(pipe) pipeclose(fp, pipe)
struct file *fp;
struct pipe *pipe; struct pipe *pipe;
{ {
struct pipe *ppipe; struct pipe *ppipe;
@ -1277,7 +1309,8 @@ pipeclose(pipe)
retry: retry:
PIPE_LOCK(pipe); PIPE_LOCK(pipe);
pipeselwakeup(pipe, pipe); if (fp)
pipeselwakeup(pipe, pipe, fp->f_data, POLL_HUP);
/* /*
* If the other side is blocked, wake it up saying that * If the other side is blocked, wake it up saying that
@ -1298,7 +1331,8 @@ retry:
PIPE_UNLOCK(pipe); PIPE_UNLOCK(pipe);
goto retry; goto retry;
} }
pipeselwakeup(ppipe, ppipe); if (fp)
pipeselwakeup(ppipe, ppipe, fp->f_data, POLL_HUP);
ppipe->pipe_state |= PIPE_EOF; ppipe->pipe_state |= PIPE_EOF;
wakeup(ppipe); wakeup(ppipe);