From a33a955163c1af459af176b3fdc1c4c56b4f25f3 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Mon, 2 Jun 2014 17:14:28 +0200 Subject: [PATCH] local: reset daemon after unexpected time jump Add a new change type and use it when an unexpected time jump is detected in the scheduler to reset reference times, offset and slewing, NCR instances (with their polling interval), synchronization status, and drop all sourcestats, manual, refclock and RTC samples. This should make the recovery more graceful if the estimated jump has a large error (e.g. select didn't timeout, or after system suspend). --- local.c | 2 +- local.h | 3 ++- manual.c | 5 +++++ ntp_sources.c | 6 +++++- refclock.c | 8 ++++++-- reference.c | 5 ++++- rtc_linux.c | 5 +++++ sources.c | 12 ++++++++++-- sys_generic.c | 9 ++++++++- test/simulation/005-externalstep | 4 ++-- 10 files changed, 48 insertions(+), 11 deletions(-) diff --git a/local.c b/local.c index 3619b58..513779e 100644 --- a/local.c +++ b/local.c @@ -479,7 +479,7 @@ LCL_NotifyExternalTimeStep(struct timeval *raw, struct timeval *cooked, double offset, double dispersion) { /* Dispatch to all handlers */ - invoke_parameter_change_handlers(raw, cooked, 0.0, offset, LCL_ChangeStep); + invoke_parameter_change_handlers(raw, cooked, 0.0, offset, LCL_ChangeUnknownStep); lcl_InvokeDispersionNotifyHandlers(dispersion); } diff --git a/local.h b/local.h index bdf38bd..4000acd 100644 --- a/local.h +++ b/local.h @@ -74,7 +74,8 @@ extern void LCL_GetOffsetCorrection(struct timeval *raw, double *correction, dou typedef enum { LCL_ChangeAdjust, - LCL_ChangeStep + LCL_ChangeStep, + LCL_ChangeUnknownStep } LCL_ChangeType; typedef void (*LCL_ParameterChangeHandler) diff --git a/manual.c b/manual.c index 011d07a..c286ce8 100644 --- a/manual.c +++ b/manual.c @@ -221,6 +221,11 @@ slew_samples(struct timeval *raw, { double delta_time; int i; + + if (change_type == LCL_ChangeUnknownStep) { + MNL_Reset(); + } + for (i=0; iip_addr), dfreq, doffset); #endif - NCR_SlewTimes(records[i].data, cooked, dfreq, doffset); + if (change_type == LCL_ChangeUnknownStep) { + NCR_ResetInstance(records[i].data); + } else { + NCR_SlewTimes(records[i].data, cooked, dfreq, doffset); + } } } diff --git a/refclock.c b/refclock.c index 83b9488..d94c73c 100644 --- a/refclock.c +++ b/refclock.c @@ -581,8 +581,12 @@ slew_samples(struct timeval *raw, struct timeval *cooked, double dfreq, { int i; - for (i = 0; i < n_sources; i++) - filter_slew_samples(&refclocks[i].filter, cooked, dfreq, doffset); + for (i = 0; i < n_sources; i++) { + if (change_type == LCL_ChangeUnknownStep) + filter_reset(&refclocks[i].filter); + else + filter_slew_samples(&refclocks[i].filter, cooked, dfreq, doffset); + } } static void diff --git a/reference.c b/reference.c index 6038ce3..503f672 100644 --- a/reference.c +++ b/reference.c @@ -147,7 +147,10 @@ handle_slew(struct timeval *raw, LCL_ChangeType change_type, void *anything) { - if (change_type == LCL_ChangeStep) { + if (change_type == LCL_ChangeUnknownStep) { + last_ref_update.tv_sec = 0; + last_ref_update.tv_usec = 0; + } else if (change_type == LCL_ChangeStep) { UTI_AddDoubleToTimeval(&last_ref_update, -doffset, &last_ref_update); } } diff --git a/rtc_linux.c b/rtc_linux.c index 602345c..88c0160 100644 --- a/rtc_linux.c +++ b/rtc_linux.c @@ -273,6 +273,11 @@ slew_samples double delta_time; double old_seconds_fast, old_gain_rate; + if (change_type == LCL_ChangeUnknownStep) { + /* Drop all samples. */ + n_samples = 0; + } + for (i=0; istats, cooked, dfreq, doffset); + if (change_type == LCL_ChangeUnknownStep) { + SST_ResetInstance(sources[i]->stats); + } else { + SST_SlewSamples(sources[i]->stats, cooked, dfreq, doffset); + } + } + + if (change_type == LCL_ChangeUnknownStep) { + /* After resetting no source is selectable, set reference unsynchronised */ + SRC_SelectSource(NULL); } - } /* ================================================== */ diff --git a/sys_generic.c b/sys_generic.c index 51c6824..2adbbfe 100644 --- a/sys_generic.c +++ b/sys_generic.c @@ -87,6 +87,7 @@ static double slew_error; /* ================================================== */ static void handle_end_of_slew(void *anything); +static void update_slew(void); /* ================================================== */ /* Adjust slew_start on clock step */ @@ -95,8 +96,14 @@ static void handle_step(struct timeval *raw, struct timeval *cooked, double dfreq, double doffset, LCL_ChangeType change_type, void *anything) { - if (change_type == LCL_ChangeStep) + if (change_type == LCL_ChangeUnknownStep) { + /* Reset offset and slewing */ + slew_start = *raw; + offset_register = 0.0; + update_slew(); + } else if (change_type == LCL_ChangeStep) { UTI_AddDoubleToTimeval(&slew_start, -doffset, &slew_start); + } } /* ================================================== */ diff --git a/test/simulation/005-externalstep b/test/simulation/005-externalstep index 3f26324..1e5527d 100755 --- a/test/simulation/005-externalstep +++ b/test/simulation/005-externalstep @@ -4,8 +4,8 @@ test_start "external time step" -min_sync_time=1300 -max_sync_time=1500 +min_sync_time=1500 +max_sync_time=1550 for step in -1e2 1e2; do # Make one step in 150th second