Try to handle unexpected backward time jumps
This commit is contained in:
parent
4ba3dd66ad
commit
91749ebb2b
3 changed files with 68 additions and 7 deletions
16
local.c
16
local.c
|
@ -488,6 +488,22 @@ LCL_ApplyStepOffset(double offset)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
void
|
||||||
|
LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
|
||||||
|
double offset, double dispersion)
|
||||||
|
{
|
||||||
|
ChangeListEntry *ptr;
|
||||||
|
|
||||||
|
/* Dispatch to all handlers */
|
||||||
|
for (ptr = change_list.next; ptr != &change_list; ptr = ptr->next) {
|
||||||
|
(ptr->handler)(raw, cooked, 0.0, offset, 1, ptr->anything);
|
||||||
|
}
|
||||||
|
|
||||||
|
lcl_InvokeDispersionNotifyHandlers(dispersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset)
|
LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset)
|
||||||
{
|
{
|
||||||
|
|
5
local.h
5
local.h
|
@ -151,6 +151,11 @@ extern void LCL_AccumulateOffset(double offset);
|
||||||
|
|
||||||
extern void LCL_ApplyStepOffset(double offset);
|
extern void LCL_ApplyStepOffset(double offset);
|
||||||
|
|
||||||
|
/* Routine to invoke notify handlers on an unexpected time jump
|
||||||
|
in system clock */
|
||||||
|
extern void LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked,
|
||||||
|
double offset, double dispersion);
|
||||||
|
|
||||||
/* Perform the combination of modifying the frequency and applying
|
/* Perform the combination of modifying the frequency and applying
|
||||||
a slew, in one easy step */
|
a slew, in one easy step */
|
||||||
extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset);
|
extern void LCL_AccumulateFrequencyAndOffset(double dfreq, double doffset);
|
||||||
|
|
54
sched.c
54
sched.c
|
@ -70,9 +70,9 @@ typedef struct {
|
||||||
|
|
||||||
static FileHandlerEntry file_handlers[FD_SET_SIZE];
|
static FileHandlerEntry file_handlers[FD_SET_SIZE];
|
||||||
|
|
||||||
/* Last timestamp when a file descriptor became readable */
|
/* Timestamp when last select() returned */
|
||||||
static struct timeval last_fdready;
|
static struct timeval last_select_ts, last_select_ts_raw;
|
||||||
static double last_fdready_err;
|
static double last_select_ts_err;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
@ -229,9 +229,9 @@ SCH_RemoveInputFileHandler(int fd)
|
||||||
void
|
void
|
||||||
SCH_GetFileReadyTime(struct timeval *tv, double *err)
|
SCH_GetFileReadyTime(struct timeval *tv, double *err)
|
||||||
{
|
{
|
||||||
*tv = last_fdready;
|
*tv = last_select_ts;
|
||||||
if (err)
|
if (err)
|
||||||
*err = last_fdready_err;
|
*err = last_select_ts_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
@ -514,13 +514,42 @@ handle_slew(struct timeval *raw,
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
/* Try to handle unexpected backward time jump */
|
||||||
|
|
||||||
|
static void
|
||||||
|
recover_backjump(struct timeval *raw, struct timeval *cooked, int timeout)
|
||||||
|
{
|
||||||
|
double diff, err;
|
||||||
|
|
||||||
|
UTI_DiffTimevalsToDouble(&diff, &last_select_ts_raw, raw);
|
||||||
|
|
||||||
|
if (n_timer_queue_entries > 0) {
|
||||||
|
UTI_DiffTimevalsToDouble(&err, &(timer_queue.next->tv), &last_select_ts_raw);
|
||||||
|
} else {
|
||||||
|
err = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff += err;
|
||||||
|
|
||||||
|
if (timeout) {
|
||||||
|
err = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(LOGS_WARN, LOGF_Scheduler, "Backward time jump detected! (correction %.1f +- %.1f seconds)", diff, err);
|
||||||
|
|
||||||
|
LCL_NotifyExternalTimeStep(raw, cooked, diff, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
SCH_MainLoop(void)
|
SCH_MainLoop(void)
|
||||||
{
|
{
|
||||||
fd_set rd;
|
fd_set rd;
|
||||||
int status;
|
int status;
|
||||||
struct timeval tv, *ptv;
|
struct timeval tv, *ptv;
|
||||||
struct timeval now;
|
struct timeval now, cooked;
|
||||||
|
double err;
|
||||||
|
|
||||||
assert(initialised);
|
assert(initialised);
|
||||||
|
|
||||||
|
@ -557,12 +586,23 @@ SCH_MainLoop(void)
|
||||||
|
|
||||||
status = select(one_highest_fd, &rd, NULL, NULL, ptv);
|
status = select(one_highest_fd, &rd, NULL, NULL, ptv);
|
||||||
|
|
||||||
|
LCL_ReadRawTime(&now);
|
||||||
|
LCL_CookTime(&now, &cooked, &err);
|
||||||
|
|
||||||
|
/* Check if time didn't jump backwards */
|
||||||
|
if (last_select_ts_raw.tv_sec > now.tv_sec + 1) {
|
||||||
|
recover_backjump(&now, &cooked, status == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
last_select_ts_raw = now;
|
||||||
|
last_select_ts = cooked;
|
||||||
|
last_select_ts_err = err;
|
||||||
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
assert(need_to_exit);
|
assert(need_to_exit);
|
||||||
} else if (status > 0) {
|
} else if (status > 0) {
|
||||||
/* A file descriptor is ready to read */
|
/* A file descriptor is ready to read */
|
||||||
|
|
||||||
LCL_ReadCookedTime(&last_fdready, &last_fdready_err);
|
|
||||||
dispatch_filehandlers(status, &rd);
|
dispatch_filehandlers(status, &rd);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue