sys_macosx: reset drift removal timer after spike in offset_sd

When a large spike occurs in offset_sd the drift removal interval can be
set to an excessively long time, although what ever event caused the
perturbation has passed. At the next set_sync_status() we now compare
the expected drift removal interval with that currently in effect. If
they are significantly different, the current timer is cancelled and new
cycle started using the new drift removal interval.
This commit is contained in:
Bryan Christianson 2015-08-28 23:21:01 +12:00 committed by Miroslav Lichvar
parent 770db1fe02
commit 67ce6bd279

View file

@ -79,6 +79,11 @@ static double adjustment_requested;
#define DRIFT_REMOVAL_INTERVAL (4.0)
#define DRIFT_REMOVAL_INTERVAL_MIN (0.5)
/* If current_drift_removal_interval / drift_removal_interval exceeds this
ratio, then restart the drift removal timer */
#define DRIFT_REMOVAL_RESTART_RATIO (8.0)
static double drift_removal_interval;
static double current_drift_removal_interval;
static struct timeval Tdrift;
@ -223,27 +228,6 @@ accrue_offset(double offset, double corr_rate)
/* ================================================== */
/* use est_error to calculate the drift_removal_interval */
static void
set_sync_status(int synchronised, double est_error, double max_error)
{
double interval;
if (!synchronised) {
drift_removal_interval = MAX(drift_removal_interval, DRIFT_REMOVAL_INTERVAL);
return;
}
interval = ERROR_WEIGHT * est_error / (fabs(current_freq) + FREQUENCY_RES);
drift_removal_interval = MAX(interval, DRIFT_REMOVAL_INTERVAL_MIN);
DEBUG_LOG(LOGF_SysMacOSX, "est_error: %.3f current_freq: %.3f est drift_removal_interval: %.3f act drift_removal_interval: %.3f",
est_error * 1.0e6, current_freq * 1.0e6, interval, drift_removal_interval);
}
/* ================================================== */
/* Positive offset means system clock is fast of true time, therefore
step backwards */
@ -340,6 +324,34 @@ drift_removal_timeout(SCH_ArbitraryArgument not_used)
drift_removal_id = SCH_AddTimeoutByDelay(drift_removal_interval, drift_removal_timeout, NULL);
}
/* ================================================== */
/* use est_error to calculate the drift_removal_interval */
static void
set_sync_status(int synchronised, double est_error, double max_error)
{
double interval;
if (!synchronised) {
drift_removal_interval = MAX(drift_removal_interval, DRIFT_REMOVAL_INTERVAL);
} else {
interval = ERROR_WEIGHT * est_error / (fabs(current_freq) + FREQUENCY_RES);
drift_removal_interval = MAX(interval, DRIFT_REMOVAL_INTERVAL_MIN);
DEBUG_LOG(LOGF_SysMacOSX, "est_error: %.3f current_freq: %.3f est drift_removal_interval: %.3f act drift_removal_interval: %.3f",
est_error * 1.0e6, current_freq * 1.0e6, interval, drift_removal_interval);
}
if (current_drift_removal_interval / drift_removal_interval > DRIFT_REMOVAL_RESTART_RATIO) {
/* recover from a large est_error by resetting the timer */
SCH_ArbitraryArgument unused;
SCH_RemoveTimeout(drift_removal_id);
unused = NULL;
drift_removal_timeout(unused);
}
}
/* ================================================== */
/*
Give chronyd real time priority so that time critical calculations