diff options
| author | Konstantin Belousov <kib@FreeBSD.org> | 2009-07-07 09:43:44 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2009-07-07 09:43:44 +0000 |
| commit | 7f5dff50646e2eb5e7cf490c0a73f49f85ab5ce1 (patch) | |
| tree | fa963c164b557f57ea4c0183ad1527b57d286d89 /sys | |
| parent | 55b57bd2746a468fdc3de857b95d4037c5cda593 (diff) | |
Notes
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/fs/fifofs/fifo_vnops.c | 34 | ||||
| -rw-r--r-- | sys/kern/sys_pipe.c | 15 | ||||
| -rw-r--r-- | sys/kern/uipc_socket.c | 19 | ||||
| -rw-r--r-- | sys/sys/socketvar.h | 5 |
4 files changed, 36 insertions, 37 deletions
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c index d328f3b4289a..25436c70f458 100644 --- a/sys/fs/fifofs/fifo_vnops.c +++ b/sys/fs/fifofs/fifo_vnops.c @@ -84,6 +84,7 @@ struct fifoinfo { struct socket *fi_writesock; long fi_readers; long fi_writers; + int fi_wgen; }; static vop_print_t fifo_print; @@ -232,6 +233,7 @@ fail1: sowwakeup(fip->fi_writesock); } } + fp->f_seqcount = fip->fi_wgen - fip->fi_writers; } if (ap->a_mode & FWRITE) { if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) { @@ -279,6 +281,9 @@ fail1: fip->fi_writers--; if (fip->fi_writers == 0) { socantrcvmore(fip->fi_readsock); + mtx_lock(&fifo_mtx); + fip->fi_wgen++; + mtx_unlock(&fifo_mtx); fifo_cleanup(vp); } return (error); @@ -395,8 +400,12 @@ fifo_close(ap) } if (ap->a_fflag & FWRITE) { fip->fi_writers--; - if (fip->fi_writers == 0) + if (fip->fi_writers == 0) { socantrcvmore(fip->fi_readsock); + mtx_lock(&fifo_mtx); + fip->fi_wgen++; + mtx_unlock(&fifo_mtx); + } } fifo_cleanup(vp); return (0); @@ -634,28 +643,13 @@ fifo_poll_f(struct file *fp, int events, struct ucred *cred, struct thread *td) levents = events & (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | POLLRDBAND); if ((fp->f_flag & FREAD) && levents) { - /* - * If POLLIN or POLLRDNORM is requested and POLLINIGNEOF is - * not, then convert the first two to the last one. This - * tells the socket poll function to ignore EOF so that we - * block if there is no writer (and no data). Callers can - * set POLLINIGNEOF to get non-blocking behavior. - */ - if (levents & (POLLIN | POLLRDNORM) && - !(levents & POLLINIGNEOF)) { - levents &= ~(POLLIN | POLLRDNORM); - levents |= POLLINIGNEOF; - } - filetmp.f_data = fip->fi_readsock; filetmp.f_cred = cred; + mtx_lock(&fifo_mtx); + if (fp->f_seqcount == fip->fi_wgen) + levents |= POLLINIGNEOF; + mtx_unlock(&fifo_mtx); revents |= soo_poll(&filetmp, levents, cred, td); - - /* Reverse the above conversion. */ - if ((revents & POLLINIGNEOF) && !(events & POLLINIGNEOF)) { - revents |= (events & (POLLIN | POLLRDNORM)); - revents &= ~POLLINIGNEOF; - } } levents = events & (POLLOUT | POLLWRNORM | POLLWRBAND); if ((fp->f_flag & FWRITE) && levents) { diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 45dc0f6588f6..ce20d280c316 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -1353,8 +1353,7 @@ pipe_poll(fp, events, active_cred, td) #endif if (events & (POLLIN | POLLRDNORM)) if ((rpipe->pipe_state & PIPE_DIRECTW) || - (rpipe->pipe_buffer.cnt > 0) || - (rpipe->pipe_state & PIPE_EOF)) + (rpipe->pipe_buffer.cnt > 0)) revents |= events & (POLLIN | POLLRDNORM); if (events & (POLLOUT | POLLWRNORM)) @@ -1364,10 +1363,14 @@ pipe_poll(fp, events, active_cred, td) (wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF)) revents |= events & (POLLOUT | POLLWRNORM); - if ((rpipe->pipe_state & PIPE_EOF) || - wpipe->pipe_present != PIPE_ACTIVE || - (wpipe->pipe_state & PIPE_EOF)) - revents |= POLLHUP; + if ((events & POLLINIGNEOF) == 0) { + if (rpipe->pipe_state & PIPE_EOF) { + revents |= (events & (POLLIN | POLLRDNORM)); + if (wpipe->pipe_present != PIPE_ACTIVE || + (wpipe->pipe_state & PIPE_EOF)) + revents |= POLLHUP; + } + } if (revents == 0) { if (events & (POLLIN | POLLRDNORM)) { diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index ecb1b7b69799..62550b2a1f8f 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -2885,14 +2885,9 @@ sopoll_generic(struct socket *so, int events, struct ucred *active_cred, SOCKBUF_LOCK(&so->so_snd); SOCKBUF_LOCK(&so->so_rcv); if (events & (POLLIN | POLLRDNORM)) - if (soreadable(so)) + if (soreadabledata(so)) revents |= events & (POLLIN | POLLRDNORM); - if (events & POLLINIGNEOF) - if (so->so_rcv.sb_cc >= so->so_rcv.sb_lowat || - !TAILQ_EMPTY(&so->so_comp) || so->so_error) - revents |= POLLINIGNEOF; - if (events & (POLLOUT | POLLWRNORM)) if (sowriteable(so)) revents |= events & (POLLOUT | POLLWRNORM); @@ -2901,10 +2896,16 @@ sopoll_generic(struct socket *so, int events, struct ucred *active_cred, if (so->so_oobmark || (so->so_rcv.sb_state & SBS_RCVATMARK)) revents |= events & (POLLPRI | POLLRDBAND); + if ((events & POLLINIGNEOF) == 0) { + if (so->so_rcv.sb_state & SBS_CANTRCVMORE) { + revents |= events & (POLLIN | POLLRDNORM); + if (so->so_snd.sb_state & SBS_CANTSENDMORE) + revents |= POLLHUP; + } + } + if (revents == 0) { - if (events & - (POLLIN | POLLINIGNEOF | POLLPRI | POLLRDNORM | - POLLRDBAND)) { + if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) { selrecord(td, &so->so_rcv.sb_sel); so->so_rcv.sb_flags |= SB_SEL; } diff --git a/sys/sys/socketvar.h b/sys/sys/socketvar.h index 2817b84fa29b..889908315d25 100644 --- a/sys/sys/socketvar.h +++ b/sys/sys/socketvar.h @@ -197,10 +197,11 @@ struct xsocket { ((so)->so_proto->pr_flags & PR_ATOMIC) /* can we read something from so? */ -#define soreadable(so) \ +#define soreadabledata(so) \ ((so)->so_rcv.sb_cc >= (so)->so_rcv.sb_lowat || \ - ((so)->so_rcv.sb_state & SBS_CANTRCVMORE) || \ !TAILQ_EMPTY(&(so)->so_comp) || (so)->so_error) +#define soreadable(so) \ + (soreadabledata(so) || ((so)->so_rcv.sb_state & SBS_CANTRCVMORE)) /* can we write something to so? */ #define sowriteable(so) \ |
