From: Willy Tarreau Date: Tue, 28 May 2019 14:44:05 +0000 (+0200) Subject: MEDIUM: poller: separate the wait time from the wake events X-Git-Tag: v2.0-dev5~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2ae84e445da0a1a390ed8a569752a42e391686db;p=thirdparty%2Fhaproxy.git MEDIUM: poller: separate the wait time from the wake events We have been abusing the do_poll()'s timeout for a while, making it zero whenever there is some known activity. The problem this poses is that it complicates activity diagnostic by incrementing the poll_exp field for each known activity. It also requires extra computations that could be avoided. This change passes a "wake" argument to say that the poller must not sleep. This simplifies the operations and allows one to differenciate expirations from activity. --- diff --git a/include/types/fd.h b/include/types/fd.h index 3ff4f656fc..9b54553eca 100644 --- a/include/types/fd.h +++ b/include/types/fd.h @@ -142,7 +142,7 @@ struct fdinfo { * - is initialized by the poller's init() function, and cleaned by * the term() function. * - clo() should be used to do indicate the poller that fd will be closed. - * - poll() calls the poller, expiring at + * - poll() calls the poller, expiring at , or immediately if is set * - flags indicate what the poller supports (HAP_POLL_F_*) */ @@ -151,7 +151,7 @@ struct fdinfo { struct poller { void *private; /* any private data for the poller */ void REGPRM1 (*clo)(const int fd); /* mark as closed */ - void REGPRM2 (*poll)(struct poller *p, int exp); /* the poller itself */ + void REGPRM3 (*poll)(struct poller *p, int exp, int wake); /* the poller itself */ int REGPRM1 (*init)(struct poller *p); /* poller initialization */ void REGPRM1 (*term)(struct poller *p); /* termination of this poller */ int REGPRM1 (*test)(struct poller *p); /* pre-init check of the poller */ diff --git a/src/ev_epoll.c b/src/ev_epoll.c index 039327d5a9..6c09c0498f 100644 --- a/src/ev_epoll.c +++ b/src/ev_epoll.c @@ -103,7 +103,7 @@ static void _update_fd(int fd) /* * Linux epoll() poller */ -REGPRM2 static void _do_poll(struct poller *p, int exp) +REGPRM3 static void _do_poll(struct poller *p, int exp, int wake) { int status; int fd; @@ -147,7 +147,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) thread_harmless_now(); /* now let's wait for polled events */ - wait_time = compute_poll_timeout(exp); + wait_time = wake ? 0 : compute_poll_timeout(exp); tv_entering_poll(); activity_count_runtime(); do { @@ -160,7 +160,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) break; if (timeout || !wait_time) break; - if (signal_queue_len) + if (signal_queue_len || wake) break; if (tick_isset(exp) && tick_is_expired(exp, now_ms)) break; diff --git a/src/ev_evports.c b/src/ev_evports.c index dbad7b790f..eae72d0991 100644 --- a/src/ev_evports.c +++ b/src/ev_evports.c @@ -96,7 +96,7 @@ static void _update_fd(int fd) * "src/fd.c" for more information. */ -REGPRM2 static void _do_poll(struct poller *p, int exp) +REGPRM3 static void _do_poll(struct poller *p, int exp, int wake) { int i; int wait_time; @@ -144,7 +144,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) /* * Determine how long to wait for events to materialise on the port. */ - wait_time = compute_poll_timeout(exp); + wait_time = wake ? 0 : compute_poll_timeout(exp); tv_entering_poll(); activity_count_runtime(); @@ -183,7 +183,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) break; if (timeout || !wait_time) break; - if (signal_queue_len) + if (signal_queue_len || wake) break; if (tick_isset(exp) && tick_is_expired(exp, now_ms)) break; diff --git a/src/ev_kqueue.c b/src/ev_kqueue.c index 674551e4d7..aea2ab7389 100644 --- a/src/ev_kqueue.c +++ b/src/ev_kqueue.c @@ -74,7 +74,7 @@ static int _update_fd(int fd, int start) /* * kqueue() poller */ -REGPRM2 static void _do_poll(struct poller *p, int exp) +REGPRM3 static void _do_poll(struct poller *p, int exp, int wake) { int status; int count, fd, wait_time; @@ -132,7 +132,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) fd_nbupdt = 0; /* now let's wait for events */ - wait_time = compute_poll_timeout(exp); + wait_time = wake ? 0 : compute_poll_timeout(exp); fd = global.tune.maxpollevents; tv_entering_poll(); activity_count_runtime(); @@ -155,7 +155,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) break; if (timeout || !wait_time) break; - if (signal_queue_len) + if (signal_queue_len || wake) break; if (tick_isset(exp) && tick_is_expired(exp, now_ms)) break; diff --git a/src/ev_poll.c b/src/ev_poll.c index 863b838972..54812f53b8 100644 --- a/src/ev_poll.c +++ b/src/ev_poll.c @@ -88,7 +88,7 @@ static void _update_fd(int fd, int *max_add_fd) /* * Poll() poller */ -REGPRM2 static void _do_poll(struct poller *p, int exp) +REGPRM3 static void _do_poll(struct poller *p, int exp, int wake) { int status; int fd; @@ -194,7 +194,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) } /* now let's wait for events */ - wait_time = compute_poll_timeout(exp); + wait_time = wake ? 0 : compute_poll_timeout(exp); tv_entering_poll(); activity_count_runtime(); status = poll(poll_events, nbfd, wait_time); diff --git a/src/ev_select.c b/src/ev_select.c index 3591f1eb1f..0ccf2f150c 100644 --- a/src/ev_select.c +++ b/src/ev_select.c @@ -79,7 +79,7 @@ static void _update_fd(int fd, int *max_add_fd) /* * Select() poller */ -REGPRM2 static void _do_poll(struct poller *p, int exp) +REGPRM3 static void _do_poll(struct poller *p, int exp, int wake) { int status; int fd, i; @@ -162,7 +162,7 @@ REGPRM2 static void _do_poll(struct poller *p, int exp) } /* now let's wait for events */ - delta_ms = compute_poll_timeout(exp); + delta_ms = wake ? 0 : compute_poll_timeout(exp); delta.tv_sec = (delta_ms / 1000); delta.tv_usec = (delta_ms % 1000) * 1000; tv_entering_poll(); diff --git a/src/haproxy.c b/src/haproxy.c index 306c34fa3b..35dd514a65 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -2505,7 +2505,7 @@ void deinit(void) /* Runs the polling loop */ static void run_poll_loop() { - int next, exp; + int next, wake; tv_update_date(0,1); while (1) { @@ -2525,7 +2525,7 @@ static void run_poll_loop() break; /* expire immediately if events are pending */ - exp = now_ms; + wake = 1; if (fd_cache_mask & tid_bit) activity[tid].wake_cache++; else if (active_tasks_mask & tid_bit) @@ -2539,11 +2539,11 @@ static void run_poll_loop() activity[tid].wake_tasks++; _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit); } else - exp = next; + wake = 0; } /* The poller will ensure it returns around */ - cur_poller.poll(&cur_poller, exp); + cur_poller.poll(&cur_poller, next, wake); if (sleeping_thread_mask & tid_bit) _HA_ATOMIC_AND(&sleeping_thread_mask, ~tid_bit); fd_process_cached_events();