2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-03 07:45:30 +00:00

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 <ethan@nicira.com>
This commit is contained in:
Ethan Jackson
2012-10-04 17:57:16 -07:00
parent 1d446463ea
commit 00a1689587

View File

@@ -58,15 +58,14 @@ static long long int boot_time;
static struct timespec warp_offset; /* Offset added to monotonic_time. */ static struct timespec warp_offset; /* Offset added to monotonic_time. */
static bool time_stopped; /* Disables real-time updates, if true. */ static bool time_stopped; /* Disables real-time updates, if true. */
/* Time at which to die with SIGALRM (if not TIME_MIN). */ /* Time in milliseconds at which to die with SIGALRM (if not LLONG_MAX). */
static time_t deadline = TIME_MIN; static long long int deadline = LLONG_MAX;
static void set_up_timer(void); static void set_up_timer(void);
static void set_up_signal(int flags); static void set_up_signal(int flags);
static void sigalrm_handler(int); static void sigalrm_handler(int);
static void refresh_wall_if_ticked(void); static void refresh_wall_if_ticked(void);
static void refresh_monotonic_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 block_sigalrm(sigset_t *);
static void unblock_sigalrm(const sigset_t *); static void unblock_sigalrm(const sigset_t *);
static void log_poll_interval(long long int last_wakeup); static void log_poll_interval(long long int last_wakeup);
@@ -174,12 +173,6 @@ time_postfork(void)
if (CACHE_TIME) { if (CACHE_TIME) {
set_up_timer(); 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; 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. */ /* Returns the current time, in seconds. */
time_t time_t
time_wall(void) time_wall(void)
@@ -286,20 +268,20 @@ time_wall_timespec(struct timespec *ts)
void void
time_alarm(unsigned int secs) time_alarm(unsigned int secs)
{ {
long long int now;
long long int msecs;
sigset_t oldsigs; sigset_t oldsigs;
time_init(); time_init();
time_refresh();
now = time_msec();
msecs = secs * 1000;
block_sigalrm(&oldsigs); block_sigalrm(&oldsigs);
deadline = secs ? time_add(time_now(), secs) : TIME_MIN; deadline = now < LLONG_MAX - msecs ? now + msecs : LLONG_MAX;
unblock_sigalrm(&oldsigs); 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: /* Like poll(), except:
@@ -331,6 +313,9 @@ time_poll(struct pollfd *pollfds, int n_pollfds, long long int timeout_when,
coverage_clear(); coverage_clear();
start = time_msec(); start = time_msec();
blocked = false; blocked = false;
timeout_when = MIN(timeout_when, deadline);
for (;;) { for (;;) {
long long int now = time_msec(); long long int now = time_msec();
int time_left; int time_left;
@@ -347,12 +332,21 @@ time_poll(struct pollfd *pollfds, int n_pollfds, long long int timeout_when,
if (retval < 0) { if (retval < 0) {
retval = -errno; retval = -errno;
} }
time_refresh(); time_refresh();
if (deadline <= time_msec()) {
fatal_signal_handler(SIGALRM);
if (retval < 0) {
retval = 0;
}
break;
}
if (retval != -EINTR) { if (retval != -EINTR) {
break; break;
} }
if (!blocked && deadline == TIME_MIN) { if (!blocked && !CACHE_TIME) {
block_sigalrm(&oldsigs); block_sigalrm(&oldsigs);
blocked = true; blocked = true;
} }
@@ -366,23 +360,11 @@ time_poll(struct pollfd *pollfds, int n_pollfds, long long int timeout_when,
return retval; 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 static void
sigalrm_handler(int sig_nr) sigalrm_handler(int sig_nr OVS_UNUSED)
{ {
wall_tick = true; wall_tick = true;
monotonic_tick = true; monotonic_tick = true;
if (deadline != TIME_MIN && time_now_sig() > deadline) {
fatal_signal_handler(sig_nr);
}
} }
static void static void