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 ff4a50c..6fd85f8 100644
--- a/include/common/config.h
+++ b/include/common/config.h
@@ -26,13 +26,6 @@
#include <common/compat.h>
#include <common/defaults.h>
-/* 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 7123377..03e3182 100644
--- a/include/proto/fd.h
+++ b/include/proto/fd.h
@@ -28,8 +28,11 @@
#include <unistd.h>
#include <common/config.h>
+#include <common/ticks.h>
+#include <common/time.h>
#include <types/fd.h>
+#include <types/global.h>
/* public variables */
@@ -528,6 +531,30 @@
HA_SPIN_UNLOCK(FD_LOCK, &fdtab[fd].lock);
}
+/* Computes the bounded poll() timeout based on the next expiration timer <next>
+ * by bounding it to MAX_DELAY_MS. <next> 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 f672c66..b9980db 100644
--- a/src/ev_epoll.c
+++ b/src/ev_epoll.c
@@ -144,21 +144,8 @@
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 e2f04f7..3d21cb0 100644
--- a/src/ev_kqueue.c
+++ b/src/ev_kqueue.c
@@ -129,23 +129,10 @@
}
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 712bdf9..0b51e8d 100644
--- a/src/ev_poll.c
+++ b/src/ev_poll.c
@@ -193,18 +193,7 @@
}
/* 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 d248d6d..0f9b87e 100644
--- a/src/ev_select.c
+++ b/src/ev_select.c
@@ -160,25 +160,10 @@
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,