From: Willy Tarreau Date: Wed, 17 Oct 2018 09:25:54 +0000 (+0200) Subject: MINOR: fd: centralize poll timeout computation in compute_poll_timeout() X-Git-Tag: v1.9-dev4~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f37ba94768b0890374e26b64fb8a0fae0a504bf5;p=thirdparty%2Fhaproxy.git MINOR: fd: centralize poll timeout computation in compute_poll_timeout() The 4 pollers all contain the same code used to compute the poll timeout. This is pointless, let's centralize this into fd.h. This also gets rid of the useless SCHEDULER_RESOLUTION macro which used to work arond a very old linux 2.2 bug causing select() to wake up slightly before the timeout. --- diff --git a/include/common/config.h b/include/common/config.h index ff4a50cef6..6fd85f8938 100644 --- a/include/common/config.h +++ b/include/common/config.h @@ -26,13 +26,6 @@ #include #include -/* this reduces the number of calls to select() by choosing appropriate - * sheduler precision in milliseconds. It should be near the minimum - * time that is needed by select() to collect all events. All timeouts - * are rounded up by adding this value prior to pass it to select(). - */ -#define SCHEDULER_RESOLUTION 9 - /* CONFIG_HAP_MEM_OPTIM * This enables use of memory pools instead of malloc()/free(). There * is no reason to disable it, except perhaps for rare debugging. diff --git a/include/proto/fd.h b/include/proto/fd.h index 7123377f99..03e318284e 100644 --- a/include/proto/fd.h +++ b/include/proto/fd.h @@ -28,8 +28,11 @@ #include #include +#include +#include #include +#include /* public variables */ @@ -528,6 +531,30 @@ static inline void fd_insert(int fd, void *owner, void (*iocb)(int fd), unsigned HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock); } +/* Computes the bounded poll() timeout based on the next expiration timer + * by bounding it to MAX_DELAY_MS. may equal TICK_ETERNITY. The pollers + * just needs to call this function right before polling to get their timeout + * value. Timeouts that are already expired (possibly due to a pending event) + * are accounted for in activity.poll_exp. + */ +static inline int compute_poll_timeout(int next) +{ + int wait_time; + + if (!tick_isset(next)) + wait_time = MAX_DELAY_MS; + else if (tick_is_expired(next, now_ms)) { + activity[tid].poll_exp++; + wait_time = 0; + } + else { + wait_time = TICKS_TO_MS(tick_remain(now_ms, next)) + 1; + if (wait_time > MAX_DELAY_MS) + wait_time = MAX_DELAY_MS; + } + return wait_time; +} + /* These are replacements for FD_SET, FD_CLR, FD_ISSET, working on uints */ static inline void hap_fd_set(int fd, unsigned int *evts) { diff --git a/src/ev_epoll.c b/src/ev_epoll.c index f672c66cbf..b9980dbed3 100644 --- a/src/ev_epoll.c +++ b/src/ev_epoll.c @@ -144,21 +144,8 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) thread_harmless_now(); - /* compute the epoll_wait() timeout */ - if (!exp) - wait_time = MAX_DELAY_MS; - else if (tick_is_expired(exp, now_ms)) { - activity[tid].poll_exp++; - wait_time = 0; - } - else { - wait_time = TICKS_TO_MS(tick_remain(now_ms, exp)) + 1; - if (wait_time > MAX_DELAY_MS) - wait_time = MAX_DELAY_MS; - } - /* now let's wait for polled events */ - + wait_time = compute_poll_timeout(exp); gettimeofday(&before_poll, NULL); status = epoll_wait(epoll_fd[tid], epoll_events, global.tune.maxpollevents, wait_time); tv_update_date(wait_time, status); diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c index e2f04f7025..3d21cb0349 100644 --- a/src/ev_kqueue.c +++ b/src/ev_kqueue.c @@ -129,23 +129,10 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) } fd_nbupdt = 0; - delta_ms = 0; - - if (!exp) { - delta_ms = MAX_DELAY_MS; - timeout.tv_sec = (MAX_DELAY_MS / 1000); - timeout.tv_nsec = (MAX_DELAY_MS % 1000) * 1000000; - } - else if (!tick_is_expired(exp, now_ms)) { - delta_ms = TICKS_TO_MS(tick_remain(now_ms, exp)) + 1; - if (delta_ms > MAX_DELAY_MS) - delta_ms = MAX_DELAY_MS; - timeout.tv_sec = (delta_ms / 1000); - timeout.tv_nsec = (delta_ms % 1000) * 1000000; - } - else - activity[tid].poll_exp++; - + /* now let's wait for events */ + delta_ms = compute_poll_timeout(exp); + timeout.tv_sec = (delta_ms / 1000); + timeout.tv_nsec = (delta_ms % 1000) * 1000000; fd = global.tune.maxpollevents; gettimeofday(&before_poll, NULL); status = kevent(kqueue_fd[tid], // int kq diff --git a/src/ev_poll.c b/src/ev_poll.c index 712bdf9918..0b51e8d01a 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -193,18 +193,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) } /* now let's wait for events */ - if (!exp) - wait_time = MAX_DELAY_MS; - else if (tick_is_expired(exp, now_ms)) { - activity[tid].poll_exp++; - wait_time = 0; - } - else { - wait_time = TICKS_TO_MS(tick_remain(now_ms, exp)) + 1; - if (wait_time > MAX_DELAY_MS) - wait_time = MAX_DELAY_MS; - } - + wait_time = compute_poll_timeout(exp); gettimeofday(&before_poll, NULL); status = poll(poll_events, nbfd, wait_time); tv_update_date(wait_time, status); diff --git a/src/ev_select.c b/src/ev_select.c index d248d6d44a..0f9b87ee31 100644 --- a/src/ev_select.c +++ b/src/ev_select.c @@ -160,25 +160,10 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) writenotnull |= (*(((int*)tmp_evts[DIR_WR])+i) = *(((int*)fd_evts[DIR_WR])+i)) != 0; } - delta_ms = 0; - delta.tv_sec = 0; - delta.tv_usec = 0; - - if (!exp) { - delta_ms = MAX_DELAY_MS; - delta.tv_sec = (MAX_DELAY_MS / 1000); - delta.tv_usec = (MAX_DELAY_MS % 1000) * 1000; - } - else if (!tick_is_expired(exp, now_ms)) { - delta_ms = TICKS_TO_MS(tick_remain(now_ms, exp)) + SCHEDULER_RESOLUTION; - if (delta_ms > MAX_DELAY_MS) - delta_ms = MAX_DELAY_MS; - delta.tv_sec = (delta_ms / 1000); - delta.tv_usec = (delta_ms % 1000) * 1000; - } - else - activity[tid].poll_exp++; - + /* now let's wait for events */ + delta_ms = compute_poll_timeout(exp); + delta.tv_sec = (delta_ms / 1000); + delta.tv_usec = (delta_ms % 1000) * 1000; gettimeofday(&before_poll, NULL); status = select(maxfd, readnotnull ? tmp_evts[DIR_RD] : NULL,