summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2009-07-07 09:43:44 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2009-07-07 09:43:44 +0000
commit7f5dff50646e2eb5e7cf490c0a73f49f85ab5ce1 (patch)
treefa963c164b557f57ea4c0183ad1527b57d286d89 /sys
parent55b57bd2746a468fdc3de857b95d4037c5cda593 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/fs/fifofs/fifo_vnops.c34
-rw-r--r--sys/kern/sys_pipe.c15
-rw-r--r--sys/kern/uipc_socket.c19
-rw-r--r--sys/sys/socketvar.h5
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) \