mirror of
https://gitlab.com/chrony/chrony.git
synced 2025-12-03 17:55:07 -05:00
sched: provide low-precision monotonic time
Measure the interval since the start in order to provide a monotonic time for periodical tasks not using timers like driftfile updates, key refresh, etc. Return the interval in the double format, but keep an integer remainder limiting the precision to 0.01 second to avoid issues with very small increments in a long-running process.
This commit is contained in:
43
sched.c
43
sched.c
@@ -65,6 +65,12 @@ static ARR_Instance file_handlers;
|
||||
static struct timespec last_select_ts, last_select_ts_raw;
|
||||
static double last_select_ts_err;
|
||||
|
||||
#define TS_MONO_PRECISION_NS 10000000U
|
||||
|
||||
/* Monotonic low-precision timestamp measuring interval since the start */
|
||||
static double last_select_ts_mono;
|
||||
static uint32_t last_select_ts_mono_ns;
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
/* Variables to handler the timer queue */
|
||||
@@ -136,6 +142,8 @@ SCH_Initialise(void)
|
||||
|
||||
LCL_ReadRawTime(&last_select_ts_raw);
|
||||
last_select_ts = last_select_ts_raw;
|
||||
last_select_ts_mono = 0.0;
|
||||
last_select_ts_mono_ns = 0;
|
||||
|
||||
initialised = 1;
|
||||
}
|
||||
@@ -249,6 +257,14 @@ SCH_GetLastEventTime(struct timespec *cooked, double *err, struct timespec *raw)
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
double
|
||||
SCH_GetLastEventMonoTime(void)
|
||||
{
|
||||
return last_select_ts_mono;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#define TQE_ALLOC_QUANTUM 32
|
||||
|
||||
static TimerQueueEntry *
|
||||
@@ -722,6 +738,31 @@ check_current_time(struct timespec *prev_raw, struct timespec *raw, int timeout,
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
update_monotonic_time(struct timespec *now, struct timespec *before)
|
||||
{
|
||||
struct timespec diff;
|
||||
|
||||
/* Avoid frequent floating-point operations and handle small
|
||||
increments to a large value */
|
||||
|
||||
UTI_DiffTimespecs(&diff, now, before);
|
||||
if (diff.tv_sec == 0) {
|
||||
last_select_ts_mono_ns += diff.tv_nsec;
|
||||
} else {
|
||||
last_select_ts_mono += fabs(UTI_TimespecToDouble(&diff) +
|
||||
last_select_ts_mono_ns / 1.0e9);
|
||||
last_select_ts_mono_ns = 0;
|
||||
}
|
||||
|
||||
if (last_select_ts_mono_ns > TS_MONO_PRECISION_NS) {
|
||||
last_select_ts_mono += last_select_ts_mono_ns / 1.0e9;
|
||||
last_select_ts_mono_ns = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
void
|
||||
SCH_MainLoop(void)
|
||||
{
|
||||
@@ -778,6 +819,8 @@ SCH_MainLoop(void)
|
||||
LCL_CookTime(&now, &cooked, &err);
|
||||
}
|
||||
|
||||
update_monotonic_time(&cooked, &last_select_ts);
|
||||
|
||||
last_select_ts_raw = now;
|
||||
last_select_ts = cooked;
|
||||
last_select_ts_err = err;
|
||||
|
||||
Reference in New Issue
Block a user