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:
parent
46f954490d
commit
bb0553e4c4
2 changed files with 46 additions and 0 deletions
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;
|
||||
|
|
3
sched.h
3
sched.h
|
@ -65,6 +65,9 @@ extern void SCH_SetFileHandlerEvent(int fd, int event, int enable);
|
|||
/* Get the time stamp taken after a file descriptor became ready or a timeout expired */
|
||||
extern void SCH_GetLastEventTime(struct timespec *cooked, double *err, struct timespec *raw);
|
||||
|
||||
/* Get a low-precision monotonic timestamp (starting at 0.0) */
|
||||
extern double SCH_GetLastEventMonoTime(void);
|
||||
|
||||
/* This queues a timeout to elapse at a given (raw) local time */
|
||||
extern SCH_TimeoutID SCH_AddTimeout(struct timespec *ts, SCH_TimeoutHandler handler, SCH_ArbitraryArgument arg);
|
||||
|
||||
|
|
Loading…
Reference in a new issue