From 6ea20b1acb9aefe3b0f73e71352269d9c629a6f7 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 11 Nov 2012 16:05:19 +0100 Subject: [PATCH] REORG: fd: move the fd state management from ev_sepoll ev_sepoll already provides everything needed to manage FD events by only manipulating the speculative I/O list. Nothing there is sepoll-specific so move all this to fd. --- include/proto/fd.h | 89 ++++++++++++++++++++++++++++++++--- src/ev_sepoll.c | 113 ++++----------------------------------------- src/fd.c | 7 ++- 3 files changed, 96 insertions(+), 113 deletions(-) diff --git a/include/proto/fd.h b/include/proto/fd.h index f0265b795..592327814 100644 --- a/include/proto/fd.h +++ b/include/proto/fd.h @@ -120,40 +120,115 @@ static inline void release_spec_entry(int fd) } } +/* + * Returns non-zero if is already monitored for events in direction . + */ +static inline int fd_ev_is_set(const int fd, int dir) +{ + if (cur_poller.is_set) + return cur_poller.is_set(fd, dir); + return ((unsigned)fdtab[fd].spec_e >> dir) & FD_EV_STATUS; +} + +/* Disable processing of events on fd for direction . Note: this + * function was optimized to be used with a constant for . + */ +static inline void fd_ev_clr(const int fd, int dir) +{ + unsigned int i = ((unsigned int)fdtab[fd].spec_e) & (FD_EV_STATUS << dir); + if (i == 0) + return; /* already disabled */ + fdtab[fd].spec_e ^= i; + updt_fd(fd); /* need an update entry to change the state */ +} + +/* Enable polling for events on fd for direction . Note: this + * function was optimized to be used with a constant for . + */ +static inline void fd_ev_wai(const int fd, int dir) +{ + unsigned int i = ((unsigned int)fdtab[fd].spec_e) & (FD_EV_STATUS << dir); + if (i == (FD_EV_POLLED << dir)) + return; /* already in desired state */ + fdtab[fd].spec_e ^= i ^ (FD_EV_POLLED << dir); + updt_fd(fd); /* need an update entry to change the state */ +} + +/* Enable processing of events on fd for direction . Note: this + * function was optimized to be used with a constant for . + */ +static inline void fd_ev_set(int fd, int dir) +{ + unsigned int i = ((unsigned int)fdtab[fd].spec_e) & (FD_EV_STATUS << dir); + + /* note that we don't care about disabling the polled state when + * enabling the active state, since it brings no benefit but costs + * some syscalls. + */ + if (i & (FD_EV_ACTIVE << dir)) + return; /* already in desired state */ + fdtab[fd].spec_e |= (FD_EV_ACTIVE << dir); + updt_fd(fd); /* need an update entry to change the state */ +} + +/* Disable processing of events on fd for both directions. */ +static inline void fd_ev_rem(const int fd) +{ + unsigned int i = ((unsigned int)fdtab[fd].spec_e) & FD_EV_CURR_MASK; + if (i == 0) + return; /* already disabled */ + fdtab[fd].spec_e ^= i; + updt_fd(fd); /* need an update entry to change the state */ +} + /* event manipulation primitives for use by I/O callbacks */ static inline void fd_want_recv(int fd) { - cur_poller.set(fd, DIR_RD); + if (cur_poller.set) + return cur_poller.set(fd, DIR_RD); + return fd_ev_set(fd, DIR_RD); } static inline void fd_stop_recv(int fd) { - cur_poller.clr(fd, DIR_RD); + if (cur_poller.clr) + return cur_poller.clr(fd, DIR_RD); + return fd_ev_clr(fd, DIR_RD); } static inline void fd_poll_recv(int fd) { - cur_poller.wai(fd, DIR_RD); + if (cur_poller.wai) + return cur_poller.wai(fd, DIR_RD); + return fd_ev_wai(fd, DIR_RD); } static inline void fd_want_send(int fd) { - cur_poller.set(fd, DIR_WR); + if (cur_poller.set) + return cur_poller.set(fd, DIR_WR); + return fd_ev_set(fd, DIR_WR); } static inline void fd_stop_send(int fd) { - cur_poller.clr(fd, DIR_WR); + if (cur_poller.clr) + return cur_poller.clr(fd, DIR_WR); + return fd_ev_clr(fd, DIR_WR); } static inline void fd_poll_send(int fd) { - cur_poller.wai(fd, DIR_WR); + if (cur_poller.wai) + return cur_poller.wai(fd, DIR_WR); + return fd_ev_wai(fd, DIR_WR); } static inline void fd_stop_both(int fd) { - cur_poller.rem(fd); + if (cur_poller.rem) + return cur_poller.rem(fd); + return fd_ev_rem(fd); } /* Prepares for being polled */ diff --git a/src/ev_sepoll.c b/src/ev_sepoll.c index ff185d3bd..c5b2a6e7a 100644 --- a/src/ev_sepoll.c +++ b/src/ev_sepoll.c @@ -30,7 +30,6 @@ static int absmaxevents = 0; // absolute maximum amounts of polled events -static int in_poll_loop = 0; // non-null if polled events are being processed /* private data */ static struct epoll_event *epoll_events; @@ -41,99 +40,6 @@ static int epoll_fd; */ static struct epoll_event ev; -/* - * Returns non-zero if is already monitored for events in direction . - */ -REGPRM2 static int __fd_is_set(const int fd, int dir) -{ -#if DEBUG_DEV - if (!fdtab[fd].owner) { - fprintf(stderr, "sepoll.fd_isset called on closed fd #%d.\n", fd); - ABORT_NOW(); - } -#endif - return ((unsigned)fdtab[fd].spec_e >> dir) & FD_EV_STATUS; -} - -/* - * 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_STATUS; - - if (i == FD_EV_POLLED) - return; /* already in desired state */ - updt_fd(fd); /* need an update entry to change the state */ - fdtab[fd].spec_e ^= (i ^ (unsigned int)FD_EV_POLLED) << dir; -} - -REGPRM2 static void __fd_set(const int fd, int dir) -{ - unsigned int i; - -#if DEBUG_DEV - if (!fdtab[fd].owner) { - fprintf(stderr, "sepoll.fd_set called on closed fd #%d.\n", fd); - ABORT_NOW(); - } -#endif - i = ((unsigned)fdtab[fd].spec_e >> dir) & FD_EV_STATUS; - - /* note that we don't care about disabling the polled state when - * enabling the active state, since it brings no benefit but costs - * some syscalls. - */ - if (i & FD_EV_ACTIVE) - return; /* already in desired state */ - updt_fd(fd); /* need an update entry to change the state */ - fdtab[fd].spec_e |= ((unsigned int)FD_EV_ACTIVE) << dir; -} - -REGPRM2 static void __fd_clr(const int fd, int dir) -{ - unsigned int i; - -#if DEBUG_DEV - if (!fdtab[fd].owner) { - fprintf(stderr, "sepoll.fd_clr called on closed fd #%d.\n", fd); - ABORT_NOW(); - } -#endif - i = ((unsigned)fdtab[fd].spec_e >> dir) & FD_EV_STATUS; - - if (i == 0) - return /* already disabled */; - updt_fd(fd); /* need an update entry to change the state */ - fdtab[fd].spec_e ^= i << dir; -} - -/* normally unused */ -REGPRM1 static void __fd_rem(int fd) -{ - __fd_clr(fd, DIR_RD); - __fd_clr(fd, DIR_WR); -} - -/* - * On valid epoll() implementations, a call to close() automatically removes - * the fds. This means that the FD will appear as previously unset. - */ -REGPRM1 static void __fd_clo(int fd) -{ - release_spec_entry(fd); - fdtab[fd].spec_e &= ~(FD_EV_CURR_MASK | FD_EV_PREV_MASK); -} - /* * speculative epoll() poller */ @@ -229,8 +135,6 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) tv_update_date(wait_time, status); measure_idle(); - in_poll_loop = 1; - /* process polled events */ for (count = 0; count < status; count++) { @@ -259,10 +163,10 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) * to poll again. */ if (fdtab[fd].ev & (FD_POLL_IN|FD_POLL_HUP|FD_POLL_ERR)) - __fd_set(fd, DIR_RD); + fd_ev_set(fd, DIR_RD); if (fdtab[fd].ev & (FD_POLL_OUT|FD_POLL_ERR)) - __fd_set(fd, DIR_WR); + fd_ev_set(fd, DIR_WR); fdtab[fd].iocb(fd); @@ -338,7 +242,6 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) spec_idx++; } - in_poll_loop = 0; /* in the end, we have processed status + spec_processed FDs */ } @@ -448,12 +351,12 @@ static void _do_register(void) p->poll = _do_poll; p->fork = _do_fork; - 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; + p->is_set = NULL; + p->set = NULL; + p->wai = NULL; + p->clr = NULL; + p->rem = NULL; + p->clo = NULL; } diff --git a/src/fd.c b/src/fd.c index 5d63cc371..271874811 100644 --- a/src/fd.c +++ b/src/fd.c @@ -116,7 +116,12 @@ unsigned int *fd_updt = NULL; // FD updates list */ void fd_delete(int fd) { - cur_poller.clo(fd); + if (cur_poller.clo) + cur_poller.clo(fd); + + release_spec_entry(fd); + fdtab[fd].spec_e &= ~(FD_EV_CURR_MASK | FD_EV_PREV_MASK); + port_range_release_port(fdinfo[fd].port_range, fdinfo[fd].local_port); fdinfo[fd].port_range = NULL; close(fd);