* to CLOCK_REALTIME. */
static clockid_t monotonic_clock;
-/* Has a timer tick occurred? Only relevant if CACHE_TIME is 1.
+/* Controls whether or not calls to clock_gettime() are cached. See
+ * time_cached() for a detailed explanation. */
+#if defined __x86_64__ && defined __linux__
+static bool cache_time = false;
+#else
+static bool cache_time = true;
+#endif
+
+/* Has a timer tick occurred? Only relevant if cache_time is true.
*
* We initialize these to true to force time_init() to get called on the first
* call to time_msec() or another function that queries the current time. */
VLOG_DBG("monotonic timer not available");
}
- if (CACHE_TIME) {
- set_up_signal(SA_RESTART);
- set_up_timer();
- }
+ set_up_signal(SA_RESTART);
+ set_up_timer();
boot_time = time_msec();
}
static timer_t timer_id; /* "static" to avoid apparent memory leak. */
struct itimerspec itimer;
+ if (!cache_time) {
+ return;
+ }
+
if (timer_create(monotonic_clock, NULL, &timer_id)) {
- VLOG_FATAL("timer_create failed (%s)", strerror(errno));
+ VLOG_WARN("timer_create failed (%s), disabling cached timing",
+ strerror(errno));
+ cache_time = false;
+ return;
}
itimer.it_interval.tv_sec = 0;
time_postfork(void)
{
time_init();
-
- if (CACHE_TIME) {
- set_up_timer();
- }
+ set_up_timer();
}
static void
/* Forces a refresh of the current time from the kernel. It is not usually
* necessary to call this function, since the time will be refreshed
* automatically at least every TIME_UPDATE_INTERVAL milliseconds. If
- * CACHE_TIME is 0, we will always refresh the current time so this
+ * cache_time is false, we will always refresh the current time so this
* function has no effect. */
void
time_refresh(void)
break;
}
- if (!blocked && !CACHE_TIME) {
+ if (!blocked && !cache_time) {
block_sigalrm(&oldsigs);
blocked = true;
}
return retval;
}
+/* True on systems (particularly x86-64 Linux) where clock_gettime() is
+ * inexpensive. On these systems, we don't bother caching the current time.
+ * Instead, we consult clock_gettime() directly when needed.
+ *
+ * False on systems where clock_gettime() is relatively expensive. On these
+ * systems, we cache the current time and set up a periodic SIGALRM to remind
+ * us to update it.
+ *
+ * Also false on systems (e.g. ESX) that don't support setting up timers based
+ * on a monotonically increasing clock. */
+bool
+time_cached(void)
+{
+ time_init();
+ return cache_time;
+}
+
static void
sigalrm_handler(int sig_nr OVS_UNUSED)
{
static void
refresh_wall_if_ticked(void)
{
- if (!CACHE_TIME || wall_tick) {
+ if (!cache_time || wall_tick) {
refresh_wall();
}
}
static void
refresh_monotonic_if_ticked(void)
{
- if (!CACHE_TIME || monotonic_tick) {
+ if (!cache_time || monotonic_tick) {
refresh_monotonic();
}
}
* ever encounter such a platform. */
BUILD_ASSERT_DECL(TYPE_IS_SIGNED(time_t));
-/* On x86-64 systems, Linux avoids using syscalls for clock_gettime().
- *
- * For systems which do invoke a system call we wait at least
- * TIME_UPDATE_INTERVAL ms between clock_gettime() calls and cache the time for
- * the interim.
- *
- * For systems which do not invoke a system call, we just call clock_gettime()
- * whenever the time is requested. As a result we don't start the background
- * SIGALRM timer unless explicitly needed by time_alarm() */
-#if defined __x86_64__ && defined __linux__
-#define CACHE_TIME 0
-#else
-#define CACHE_TIME 1
-#endif
-
#define TIME_MAX TYPE_MAXIMUM(time_t)
#define TIME_MIN TYPE_MINIMUM(time_t)
void time_alarm(unsigned int secs);
int time_poll(struct pollfd *, int n_pollfds, long long int timeout_when,
int *elapsed);
+bool time_cached(void);
long long int timespec_to_msec(const struct timespec *);
long long int timeval_to_msec(const struct timeval *);