From: Ethan Jackson Date: Fri, 5 Oct 2012 00:57:16 +0000 (-0700) Subject: timeval: Don't require signals for time_alarm(). X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=00a16895875658e14f0c95a5e7d179b70b7c57b5;p=openvswitch timeval: Don't require signals for time_alarm(). Before this patch, time_alarm() used the SIGALRM handler to notify the poll loop that it should exit the program. Instead, this patch simply implements time_alarm() directly in the pool loop. This significantly simplifies the code, while removing a call to timer_create() which is not currently supported on ESX. Signed-off-by: Ethan Jackson --- diff --git a/lib/timeval.c b/lib/timeval.c index 3d339e4e..835b91f7 100644 --- a/lib/timeval.c +++ b/lib/timeval.c @@ -58,15 +58,14 @@ static long long int boot_time; static struct timespec warp_offset; /* Offset added to monotonic_time. */ static bool time_stopped; /* Disables real-time updates, if true. */ -/* Time at which to die with SIGALRM (if not TIME_MIN). */ -static time_t deadline = TIME_MIN; +/* Time in milliseconds at which to die with SIGALRM (if not LLONG_MAX). */ +static long long int deadline = LLONG_MAX; static void set_up_timer(void); static void set_up_signal(int flags); static void sigalrm_handler(int); static void refresh_wall_if_ticked(void); static void refresh_monotonic_if_ticked(void); -static time_t time_add(time_t, time_t); static void block_sigalrm(sigset_t *); static void unblock_sigalrm(const sigset_t *); static void log_poll_interval(long long int last_wakeup); @@ -174,12 +173,6 @@ time_postfork(void) if (CACHE_TIME) { set_up_timer(); - } else { - /* If we are not caching kernel time, the only reason the timer should - * exist is if time_alarm() was called and deadline is set */ - if (deadline != TIME_MIN) { - set_up_timer(); - } } } @@ -228,17 +221,6 @@ time_now(void) return monotonic_time.tv_sec; } -/* Same as time_now() except does not write to static variables, for use in - * signal handlers. */ -static time_t -time_now_sig(void) -{ - struct timespec cur_time; - - clock_gettime(monotonic_clock, &cur_time); - return cur_time.tv_sec; -} - /* Returns the current time, in seconds. */ time_t time_wall(void) @@ -286,20 +268,20 @@ time_wall_timespec(struct timespec *ts) void time_alarm(unsigned int secs) { + long long int now; + long long int msecs; + sigset_t oldsigs; time_init(); + time_refresh(); + + now = time_msec(); + msecs = secs * 1000; block_sigalrm(&oldsigs); - deadline = secs ? time_add(time_now(), secs) : TIME_MIN; + deadline = now < LLONG_MAX - msecs ? now + msecs : LLONG_MAX; unblock_sigalrm(&oldsigs); - - if (!CACHE_TIME) { - /* If we aren't timing the gaps between kernel time refreshes we need to - * to start the timer up now */ - set_up_signal(SA_RESTART); - set_up_timer(); - } } /* Like poll(), except: @@ -331,6 +313,9 @@ time_poll(struct pollfd *pollfds, int n_pollfds, long long int timeout_when, coverage_clear(); start = time_msec(); blocked = false; + + timeout_when = MIN(timeout_when, deadline); + for (;;) { long long int now = time_msec(); int time_left; @@ -347,12 +332,21 @@ time_poll(struct pollfd *pollfds, int n_pollfds, long long int timeout_when, if (retval < 0) { retval = -errno; } + time_refresh(); + if (deadline <= time_msec()) { + fatal_signal_handler(SIGALRM); + if (retval < 0) { + retval = 0; + } + break; + } + if (retval != -EINTR) { break; } - if (!blocked && deadline == TIME_MIN) { + if (!blocked && !CACHE_TIME) { block_sigalrm(&oldsigs); blocked = true; } @@ -366,23 +360,11 @@ time_poll(struct pollfd *pollfds, int n_pollfds, long long int timeout_when, return retval; } -/* Returns the sum of 'a' and 'b', with saturation on overflow or underflow. */ -static time_t -time_add(time_t a, time_t b) -{ - return (a >= 0 - ? (b > TIME_MAX - a ? TIME_MAX : a + b) - : (b < TIME_MIN - a ? TIME_MIN : a + b)); -} - static void -sigalrm_handler(int sig_nr) +sigalrm_handler(int sig_nr OVS_UNUSED) { wall_tick = true; monotonic_tick = true; - if (deadline != TIME_MIN && time_now_sig() > deadline) { - fatal_signal_handler(sig_nr); - } } static void