summaryrefslogtreecommitdiffstats
path: root/libnetdata/clocks
diff options
context:
space:
mode:
authorMarkos Fountoulakis <44345837+mfundul@users.noreply.github.com>2019-02-18 18:29:29 +0200
committerGitHub <noreply@github.com>2019-02-18 18:29:29 +0200
commite0d6a2f5fac251479c99463d70e65d9674a50796 (patch)
treed876f29eb409bb104fb21d5f4ce4fb8fcfcd0d22 /libnetdata/clocks
parent2881c3e5a181d65a95d3f3d68d22bfe2f5c62a1d (diff)
When running a binary with CLOCK_BOOTTIME defined on a system with a linux (#5415)
kernel older than Linux 2.6.39 the clock_gettime(2) system call fails with EINVAL. In that case it must fall-back to CLOCK_MONOTONIC.
Diffstat (limited to 'libnetdata/clocks')
-rw-r--r--libnetdata/clocks/clocks.c14
-rw-r--r--libnetdata/clocks/clocks.h6
2 files changed, 17 insertions, 3 deletions
diff --git a/libnetdata/clocks/clocks.c b/libnetdata/clocks/clocks.c
index f303ccddcb..f7d2171780 100644
--- a/libnetdata/clocks/clocks.c
+++ b/libnetdata/clocks/clocks.c
@@ -2,6 +2,8 @@
#include "../libnetdata.h"
+static int clock_boottime_valid = 1;
+
#ifndef HAVE_CLOCK_GETTIME
inline int clock_gettime(clockid_t clk_id, struct timespec *ts) {
struct timeval tv;
@@ -15,6 +17,12 @@ inline int clock_gettime(clockid_t clk_id, struct timespec *ts) {
}
#endif
+void test_clock_boottime(void) {
+ struct timespec ts;
+ if(clock_gettime(CLOCK_BOOTTIME, &ts) == -1 && errno == EINVAL)
+ clock_boottime_valid = 0;
+}
+
static inline time_t now_sec(clockid_t clk_id) {
struct timespec ts;
if(unlikely(clock_gettime(clk_id, &ts) == -1)) {
@@ -73,15 +81,15 @@ inline int now_monotonic_timeval(struct timeval *tv) {
}
inline time_t now_boottime_sec(void) {
- return now_sec(CLOCK_BOOTTIME);
+ return now_sec(likely(clock_boottime_valid) ? CLOCK_BOOTTIME : CLOCK_MONOTONIC);
}
inline usec_t now_boottime_usec(void) {
- return now_usec(CLOCK_BOOTTIME);
+ return now_usec(likely(clock_boottime_valid) ? CLOCK_BOOTTIME : CLOCK_MONOTONIC);
}
inline int now_boottime_timeval(struct timeval *tv) {
- return now_timeval(CLOCK_BOOTTIME, tv);
+ return now_timeval(likely(clock_boottime_valid) ? CLOCK_BOOTTIME : CLOCK_MONOTONIC, tv);
}
inline usec_t timeval_usec(struct timeval *tv) {
diff --git a/libnetdata/clocks/clocks.h b/libnetdata/clocks/clocks.h
index d576d86b98..47aa148c12 100644
--- a/libnetdata/clocks/clocks.h
+++ b/libnetdata/clocks/clocks.h
@@ -130,4 +130,10 @@ extern usec_t heartbeat_monotonic_dt_to_now_usec(heartbeat_t *hb);
extern int sleep_usec(usec_t usec);
+/*
+ * When running a binary with CLOCK_BOOTTIME defined on a system with a linux kernel older than Linux 2.6.39 the
+ * clock_gettime(2) system call fails with EINVAL. In that case it must fall-back to CLOCK_MONOTONIC.
+ */
+void test_clock_boottime(void);
+
#endif /* NETDATA_CLOCKS_H */