From babd05a6c6d3a9f835b0f978c7f159d06338eb58 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 9 Aug 2012 12:14:03 +0200 Subject: [PATCH] MEDIUM: fd: add fd_poll_{recv,send} for use when explicit polling is required The old EV_FD_SET() macro was confusing, as it would enable receipt but there was no way to indicate that EAGAIN was received, hence the recently added FD_WAIT_* flags. They're not enough as we're still facing a conflict between EV_FD_* and FD_WAIT_*. So let's offer I/O functions what they need to explicitly request polling. --- include/proto/fd.h | 10 ++++++++++ include/types/fd.h | 1 + src/ev_epoll.c | 1 + src/ev_kqueue.c | 1 + src/ev_poll.c | 1 + src/ev_select.c | 1 + src/ev_sepoll.c | 21 +++++++++++++++++++++ 7 files changed, 36 insertions(+) diff --git a/include/proto/fd.h b/include/proto/fd.h index 072d3f6410..bfce1206d3 100644 --- a/include/proto/fd.h +++ b/include/proto/fd.h @@ -83,6 +83,11 @@ static inline void fd_stop_recv(int fd) cur_poller.clr(fd, DIR_RD); } +static inline void fd_poll_recv(int fd) +{ + cur_poller.wai(fd, DIR_RD); +} + static inline void fd_want_send(int fd) { cur_poller.set(fd, DIR_WR); @@ -93,6 +98,11 @@ static inline void fd_stop_send(int fd) cur_poller.clr(fd, DIR_WR); } +static inline void fd_poll_send(int fd) +{ + cur_poller.wai(fd, DIR_WR); +} + static inline void fd_stop_both(int fd) { cur_poller.rem(fd); diff --git a/include/types/fd.h b/include/types/fd.h index 2e350b8289..c6e47f2033 100644 --- a/include/types/fd.h +++ b/include/types/fd.h @@ -100,6 +100,7 @@ struct poller { int REGPRM2 (*is_set)(const int fd, int dir); /* check if is being polled for dir */ void REGPRM2 (*set)(const int fd, int dir); /* set polling on for */ void REGPRM2 (*clr)(const int fd, int dir); /* clear polling on for */ + void REGPRM2 (*wai)(const int fd, int dir); /* wait for polling on for */ void REGPRM1 (*rem)(const int fd); /* remove any polling on */ void REGPRM1 (*clo)(const int fd); /* mark as closed */ void REGPRM2 (*poll)(struct poller *p, int exp); /* the poller itself */ diff --git a/src/ev_epoll.c b/src/ev_epoll.c index 6c8408bc0d..a566917bac 100644 --- a/src/ev_epoll.c +++ b/src/ev_epoll.c @@ -396,6 +396,7 @@ static void _do_register(void) p->is_set = __fd_is_set; p->set = __fd_set; + p->wai = __fd_set; p->clr = __fd_clr; p->rem = __fd_rem; p->clo = __fd_clo; diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c index 4bfbf1bf88..e771c33a31 100644 --- a/src/ev_kqueue.c +++ b/src/ev_kqueue.c @@ -274,6 +274,7 @@ static void _do_register(void) p->is_set = __fd_is_set; p->set = __fd_set; + p->wai = __fd_set; p->clr = __fd_clr; p->rem = __fd_rem; p->clo = __fd_clo; diff --git a/src/ev_poll.c b/src/ev_poll.c index f72dfe2867..b05fec14fe 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -230,6 +230,7 @@ static void _do_register(void) p->poll = _do_poll; p->is_set = __fd_is_set; p->set = __fd_set; + p->wai = __fd_set; p->clr = __fd_clr; p->clo = p->rem = __fd_rem; } diff --git a/src/ev_select.c b/src/ev_select.c index cf4526216b..100bc57565 100644 --- a/src/ev_select.c +++ b/src/ev_select.c @@ -227,6 +227,7 @@ static void _do_register(void) p->poll = _do_poll; p->is_set = __fd_is_set; p->set = __fd_set; + p->wai = __fd_set; p->clr = __fd_clr; p->clo = p->rem = __fd_rem; } diff --git a/src/ev_sepoll.c b/src/ev_sepoll.c index 62ee1156e2..506ab3103e 100644 --- a/src/ev_sepoll.c +++ b/src/ev_sepoll.c @@ -215,6 +215,26 @@ REGPRM2 static int __fd_is_set(const int fd, int dir) * Don't worry about the strange constructs in __fd_set/__fd_clr, they are * designed like this in order to reduce the number of jumps (verified). */ +REGPRM2 static void __fd_wai(const int fd, int dir) +{ + unsigned int i; + +#if DEBUG_DEV + if (!fdtab[fd].owner) { + fprintf(stderr, "sepoll.fd_wai called on closed fd #%d.\n", fd); + ABORT_NOW(); + } +#endif + i = ((unsigned)fdtab[fd].spec.e >> dir) & FD_EV_MASK_DIR; + + if (!(i & FD_EV_IN_SL)) { + if (i == FD_EV_WAIT) + return; /* already in desired state */ + alloc_spec_entry(fd); /* need a spec entry */ + } + fdtab[fd].spec.e ^= (i ^ (unsigned int)FD_EV_IN_PL) << dir; +} + REGPRM2 static void __fd_set(const int fd, int dir) { unsigned int i; @@ -592,6 +612,7 @@ static void _do_register(void) p->is_set = __fd_is_set; p->set = __fd_set; + p->wai = __fd_wai; p->clr = __fd_clr; p->rem = __fd_rem; p->clo = __fd_clo; -- 2.47.3