From ff58d5f9028f082e62734145a03f22d3edb34efa Mon Sep 17 00:00:00 2001 From: Daniel Stodden Date: Tue, 15 Feb 2011 01:37:45 -0800 Subject: [PATCH] PR-1129: Fix main loop timeout bug. Calls to scheduler_check_fd_events return prematurely, failing to mark a timeout pending, iff nfds is 0. This leads to a condition where the deadline never gets reset, so the next calculated timeout tv will be {0, 0} and we're left spinning in select()s. Fixed by separating fd and timeout checks. Signed-off-by: Daniel Stodden --- drivers/scheduler.c | 54 +++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/drivers/scheduler.c b/drivers/scheduler.c index 3274719..43e1383 100644 --- a/drivers/scheduler.c +++ b/drivers/scheduler.c @@ -35,7 +35,7 @@ #include "scheduler.h" #include "tapdisk-log.h" -#define DBG(_f, _a...) tlog_write(TLOG_DBG, _f, ##_a) +#define DBG(_f, _a...) if (0) { tlog_syslog(TLOG_DBG, _f, ##_a); } #define BUG_ON(_cond) if (_cond) td_panic() #define SCHEDULER_MAX_TIMEOUT 600 @@ -117,17 +117,14 @@ scheduler_prepare_events(scheduler_t *s) } static int -scheduler_check_events(scheduler_t *s, int nfds) +scheduler_check_fd_events(scheduler_t *s, int nfds) { event_t *event; - struct timeval now; - - if (nfds <= 0) - return nfds; - - gettimeofday(&now, NULL); scheduler_for_each_event(s, event) { + if (!nfds) + break; + if (event->dead) continue; @@ -151,16 +148,45 @@ scheduler_check_events(scheduler_t *s, int nfds) event->pending |= SCHEDULER_POLL_EXCEPT_FD; --nfds; } + } + + return nfds; +} + +static void +scheduler_check_timeouts(scheduler_t *s) +{ + struct timeval now; + event_t *event; + + gettimeofday(&now, NULL); + + scheduler_for_each_event(s, event) { + BUG_ON(event->pending && event->masked); - if (event->pending) { - BUG_ON(event->masked); + if (event->dead) + continue; + + if (event->pending) + continue; + + if (!(event->mode & SCHEDULER_POLL_TIMEOUT)) continue; - } - if ((event->mode & SCHEDULER_POLL_TIMEOUT) && - (event->deadline <= now.tv_sec)) - event->pending = SCHEDULER_POLL_TIMEOUT; + if (event->deadline > now.tv_sec) + continue; + + event->pending = SCHEDULER_POLL_TIMEOUT; } +} + +static int +scheduler_check_events(scheduler_t *s, int nfds) +{ + if (nfds) + nfds = scheduler_check_fd_events(s, nfds); + + scheduler_check_timeouts(s); return nfds; } -- 2.39.5