summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBaptiste Jonglez <git@bitsofnetworks.org>2016-09-05 22:02:40 +0200
committerBaptiste Jonglez <git@bitsofnetworks.org>2016-11-12 19:29:39 +0100
commita3d894000b7243e4bfd54f99de3bee8154827897 (patch)
treecb8870c2922315e1491763303ed084337ecc2020
parent8b2638c349f780a0a66f6b4ef2430747d97bf24b (diff)
Use a monotonic clock instead of a realtime clock
Using a realtime clock is a bad idea: it is affected by any kind of time change, which can happen when the administrator modifies the system time, or more simply when a laptop suspends to RAM and then wakes up from sleep. With the current approach of using a realtime clock: - if the system time jumps forward (e.g. when resuming after a suspend-to-RAM), bmon would take 100% CPU and display random graph data extremely fast, until it "catches up" with the new time. - if the system time jumps backwards, bmon would freeze until *time* "catches up" to the point it was before. bmon then (incorrectly) displays a spike in the graph, because lots of packets have been sent/received since the last update. Instead of using gettimeofday(), switch to clock_gettime() with CLOCK_MONOTONIC on systems that support it. OS X does not provide clock_gettime(), so this commit also adds a Mach-specific implementation. This change has been tested on Linux 4.1 with glibc and musl, and on FreeBSD 10.0-RELEASE-p12.
-rw-r--r--configure.ac5
-rw-r--r--include/bmon/defs.h.in9
-rw-r--r--src/utils.c22
3 files changed, 28 insertions, 8 deletions
diff --git a/configure.ac b/configure.ac
index 70adab3..f1439e1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -58,7 +58,7 @@ AC_CHECK_HEADERS(sys/param.h sys/socket.h)
AC_CHECK_TYPES(suseconds_t)
-AC_CHECK_FUNCS(atexit gettimeofday memset pow socket strcasecmp)
+AC_CHECK_FUNCS(atexit clock_gettime memset pow socket strcasecmp)
AC_CHECK_FUNCS(strchr strdup strerror strncasecmp strstr strtol)
AC_CHECK_FUNCS(uname getdate)
@@ -86,6 +86,9 @@ esac
AC_CHECK_LIB(m, pow, [], AC_MSG_ERROR([requires libm]))
+# Don't fail if not found (for instance, OS X does not have clock_gettime)
+AC_CHECK_LIB(rt, clock_gettime, [], [])
+
BMON_LIB=""
#####################################################################
diff --git a/include/bmon/defs.h.in b/include/bmon/defs.h.in
index d176c30..92b72eb 100644
--- a/include/bmon/defs.h.in
+++ b/include/bmon/defs.h.in
@@ -9,6 +9,9 @@
/* Define to 1 if you have the `atexit' function. */
#undef HAVE_ATEXIT
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
/* have curses */
#undef HAVE_CURSES
@@ -39,15 +42,15 @@
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
-/* Define to 1 if you have the `gettimeofday' function. */
-#undef HAVE_GETTIMEOFDAY
-
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
+/* Define to 1 if you have the `rt' library (-lrt). */
+#undef HAVE_LIBRT
+
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
diff --git a/src/utils.c b/src/utils.c
index 248d829..7db96e7 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -27,6 +27,11 @@
#include <bmon/conf.h>
#include <bmon/utils.h>
+#ifdef __MACH__
+#include <mach/clock.h>
+#include <mach/mach.h>
+#endif
+
void *xcalloc(size_t n, size_t s)
{
void *d = calloc(n, s);
@@ -112,12 +117,21 @@ int timestamp_is_negative(timestamp_t *ts)
void update_timestamp(timestamp_t *dst)
{
- struct timeval tv;
+#ifdef __MACH__
+ clock_serv_t cclock;
+ mach_timespec_t tp;
- gettimeofday(&tv, NULL);
+ host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
+ clock_get_time(cclock, &tp);
+ mach_port_deallocate(mach_task_self(), cclock);
+#else
+ struct timespec tp;
+
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+#endif
- dst->tv_sec = tv.tv_sec;
- dst->tv_usec = tv.tv_usec;
+ dst->tv_sec = tp.tv_sec;
+ dst->tv_usec = tp.tv_nsec / 1000;
}
void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2)