fix clock resolution detection (#16720)
* fix clock resolution detection * print the delta * make sure the resolution is usec_t * use defines for default and max resolution * fixed wrong calculation
Costa Tsaousis committed
Jan 3, 2024 at 18:44 UTC
09db66cade4360b245cdc2f266bc07903938dba1
1 file changed
+28
-15
libnetdata/clocks/clocks.c
+28
-15
@@ -7,8 +7,14 @@
7
static clockid_t clock_boottime_to_use = CLOCK_MONOTONIC;
8
static clockid_t clock_monotonic_to_use = CLOCK_MONOTONIC;
9
10
-usec_t clock_monotonic_resolution = 1000;
11
-usec_t clock_realtime_resolution = 1000;
10
+// the default clock resolution is 1ms
11
+#define DEFAULT_CLOCK_RESOLUTION_UT ((usec_t)0 * USEC_PER_SEC + (usec_t)1 * USEC_PER_MS)
12
+
13
+// the max clock resolution is 10ms
14
+#define MAX_CLOCK_RESOLUTION_UT ((usec_t)0 * USEC_PER_SEC + (usec_t)10 * USEC_PER_MS)
15
+
16
+usec_t clock_monotonic_resolution = DEFAULT_CLOCK_RESOLUTION_UT;
17
+usec_t clock_realtime_resolution = DEFAULT_CLOCK_RESOLUTION_UT;
18
19
#ifndef HAVE_CLOCK_GETTIME
20
inline int clock_gettime(clockid_t clk_id __maybe_unused, struct timespec *ts) {
@@ -50,9 +56,24 @@ static void test_clock_boottime(void) {
56
}
57
58
static usec_t get_clock_resolution(clockid_t clock) {
53
- struct timespec ts;
54
- clock_getres(clock, &ts);
55
- return ts.tv_sec * USEC_PER_SEC + ts.tv_nsec * NSEC_PER_USEC;
59
+ struct timespec ts = { 0 };
60
+
61
+ if(clock_getres(clock, &ts) == 0) {
62
+ usec_t ret = (usec_t)ts.tv_sec * USEC_PER_SEC + (usec_t)ts.tv_nsec / NSEC_PER_USEC;
63
+ if(!ret && ts.tv_nsec > 0 && ts.tv_nsec < NSEC_PER_USEC)
64
+ return (usec_t)1;
65
+
66
+ else if(ret > MAX_CLOCK_RESOLUTION_UT) {
67
+ nd_log(NDLS_DAEMON, NDLP_ERR, "clock_getres(%d) returned %"PRIu64" usec is out of range, using defaults for clock resolution.", (int)clock, ret);
68
+ return DEFAULT_CLOCK_RESOLUTION_UT;
69
+ }
70
+
71
+ return ret;
72
+ }
73
+ else {
74
+ nd_log(NDLS_DAEMON, NDLP_ERR, "clock_getres(%d) failed, using defaults for clock resolution.", (int)clock);
75
+ return DEFAULT_CLOCK_RESOLUTION_UT;
76
+ }
77
}
78
79
// perform any initializations required for clocks
@@ -66,14 +87,6 @@ void clocks_init(void) {
87
88
clock_monotonic_resolution = get_clock_resolution(clock_monotonic_to_use);
89
clock_realtime_resolution = get_clock_resolution(CLOCK_REALTIME);
69
-
70
- // if for any reason these are zero, netdata will crash
71
- // since we use them as modulo to calculations
72
- if(!clock_realtime_resolution)
73
- clock_realtime_resolution = 1000;
74
-
75
- if(!clock_monotonic_resolution)
76
- clock_monotonic_resolution = 1000;
90
}
91
92
inline time_t now_sec(clockid_t clk_id) {
@@ -91,7 +104,7 @@ inline usec_t now_usec(clockid_t clk_id) {
104
netdata_log_error("clock_gettime(%d, ×pec) failed.", clk_id);
105
return 0;
106
}
94
- return (usec_t)ts.tv_sec * USEC_PER_SEC + (ts.tv_nsec % NSEC_PER_SEC) / NSEC_PER_USEC;
107
+ return (usec_t)ts.tv_sec * USEC_PER_SEC + (usec_t)(ts.tv_nsec % NSEC_PER_SEC) / NSEC_PER_USEC;
108
}
109
110
inline int now_timeval(clockid_t clk_id, struct timeval *tv) {
@@ -279,7 +292,7 @@ void heartbeat_statistics(usec_t *min_ptr, usec_t *max_ptr, usec_t *average_ptr,
292
293
inline void heartbeat_init(heartbeat_t *hb) {
294
hb->realtime = 0ULL;
282
- hb->randomness = 250 * USEC_PER_MS + ((now_realtime_usec() * clock_realtime_resolution) % (250 * USEC_PER_MS));
295
+ hb->randomness = (usec_t)250 * USEC_PER_MS + ((usec_t)(now_realtime_usec() * clock_realtime_resolution) % (250 * USEC_PER_MS));
296
hb->randomness -= (hb->randomness % clock_realtime_resolution);
297
298
netdata_mutex_lock(&heartbeat_alignment_mutex);