summaryrefslogtreecommitdiffstats
path: root/libnetdata/clocks/clocks.h
blob: d3475df6af531551a4496088c4dfa84ec7f010b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef NETDATA_CLOCKS_H
#define NETDATA_CLOCKS_H 1

#include "../libnetdata.h"

#ifndef HAVE_STRUCT_TIMESPEC
struct timespec {
    time_t tv_sec;  /* seconds */
    long   tv_nsec; /* nanoseconds */
};
#endif

#ifndef HAVE_CLOCKID_T
typedef int clockid_t;
#endif

typedef unsigned long long nsec_t;
typedef unsigned long long msec_t;
typedef unsigned long long usec_t;
typedef long long susec_t;

typedef struct heartbeat {
    usec_t monotonic;
    usec_t realtime;
} heartbeat_t;

/* Linux value is as good as any other */
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME  0
#endif

#ifndef CLOCK_MONOTONIC
/* fallback to CLOCK_REALTIME if not available */
#define CLOCK_MONOTONIC CLOCK_REALTIME
#endif

/* Prefer CLOCK_MONOTONIC_COARSE where available to reduce overhead. It has the same semantics as CLOCK_MONOTONIC */
#ifndef CLOCK_MONOTONIC_COARSE
/* fallback to CLOCK_MONOTONIC if not available */
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
#endif

#ifndef CLOCK_BOOTTIME

#ifdef CLOCK_UPTIME
/* CLOCK_BOOTTIME falls back to CLOCK_UPTIME on FreeBSD */
#define CLOCK_BOOTTIME CLOCK_UPTIME
#else // CLOCK_UPTIME
/* CLOCK_BOOTTIME falls back to CLOCK_MONOTONIC */
#define CLOCK_BOOTTIME  CLOCK_MONOTONIC_COARSE
#endif // CLOCK_UPTIME

#else // CLOCK_BOOTTIME

#ifdef HAVE_CLOCK_GETTIME
#define CLOCK_BOOTTIME_IS_AVAILABLE 1 // required for /proc/uptime
#endif // HAVE_CLOCK_GETTIME

#endif // CLOCK_BOOTTIME

#ifndef NSEC_PER_MSEC
#define NSEC_PER_MSEC   1000000ULL
#endif

#ifndef NSEC_PER_SEC
#define NSEC_PER_SEC    1000000000ULL
#endif
#ifndef NSEC_PER_USEC
#define NSEC_PER_USEC   1000ULL
#endif

#ifndef USEC_PER_SEC
#define USEC_PER_SEC    1000000ULL
#endif
#ifndef MSEC_PER_SEC
#define MSEC_PER_SEC    1000ULL
#endif

#define USEC_PER_MS     1000ULL

#ifndef HAVE_CLOCK_GETTIME
/* Fallback function for POSIX.1-2001 clock_gettime() function.
 *
 * We use a realtime clock from gettimeofday(), this will
 * make systems without clock_gettime() support sensitive
 * to time jumps or hibernation/suspend side effects.
 */
extern int clock_gettime(clockid_t clk_id, struct timespec *ts);
#endif

/*
 * Three clocks are available (cf. man 3 clock_gettime):
 *
 * REALTIME clock (i.e. wall-clock):
 *  This clock is affected by discontinuous jumps in the system time
 *  (e.g., if the system administrator manually changes the clock), and by the incremental adjustments performed by adjtime(3) and NTP.
 *
 * MONOTONIC clock
 *  Clock that cannot be set and represents monotonic time since some unspecified starting point.
 *  This clock is not affected by discontinuous jumps in the system time
 *  (e.g., if the system administrator manually changes the clock), but is affected by the incremental adjustments performed by adjtime(3) and NTP.
 *  If not available on the system, this clock falls back to REALTIME clock.
 *
 * BOOTTIME clock
 *  Identical to  CLOCK_MONOTONIC, except it also includes any time that the system is suspended.
 *  This allows applications to get a suspend-aware monotonic clock without having to deal with the complications of CLOCK_REALTIME,
 *  which may have discontinuities if the time is changed using settimeofday(2).
 *  If not available on the system, this clock falls back to MONOTONIC clock.
 *
 * All now_*_timeval() functions fill the `struct timeval` with the time from the appropriate clock.
 * Those functions return 0 on success, -1 else with errno set appropriately.
 *
 * All now_*_sec() functions return the time in seconds from the appropriate clock, or 0 on error.
 * All now_*_usec() functions return the time in microseconds from the appropriate clock, or 0 on error.
 *
 * Most functions will attempt to use CLOCK_MONOTONIC_COARSE if available to reduce contention overhead and improve
 * performance scaling. If high precision is required please use one of the available now_*_high_precision_* functions.
 */
extern int now_realtime_timeval(struct timeval *tv);
extern time_t now_realtime_sec(void);
extern usec_t now_realtime_usec(void);

extern int now_monotonic_timeval(struct timeval *tv);
extern time_t now_monotonic_sec(void);
extern usec_t now_monotonic_usec(void);
extern int now_monotonic_high_precision_timeval(struct timeval *tv);
extern time_t now_monotonic_high_precision_sec(void);
extern usec_t now_monotonic_high_precision_usec(void);

extern int now_boottime_timeval(struct timeval *tv);
extern time_t now_boottime_sec(void);
extern usec_t now_boottime_usec(void);


extern usec_t timeval_usec(struct timeval *tv);
extern msec_t timeval_msec(struct timeval *tv);

extern usec_t dt_usec(struct timeval *now, struct timeval *old);
extern susec_t dt_usec_signed(struct timeval *now, struct timeval *old);

extern void heartbeat_init(heartbeat_t *hb);

/* Sleeps until next multiple of tick using monotonic clock.
 * Returns elapsed time in microseconds since previous heartbeat
 */
extern usec_t heartbeat_next(heartbeat_t *hb, usec_t tick);

/* Returns elapsed time in microseconds since last heartbeat */
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);

/*
 * When running a binary with CLOCK_MONOTONIC_COARSE defined on a system with a linux kernel older than Linux 2.6.32 the
 * clock_gettime(2) system call fails with EINVAL. In that case it must fall-back to CLOCK_MONOTONIC.
 */
void test_clock_monotonic_coarse(void);

extern collected_number uptime_msec(char *filename);

#endif /* NETDATA_CLOCKS_H */