sys: add sync status setting to generic and Linux driver
Set the adjtimex status, esterror and maxerror fields to the values provided by the reference module.
This commit is contained in:
parent
2645e632a8
commit
02cbe5e1ad
5 changed files with 54 additions and 17 deletions
|
@ -38,6 +38,7 @@ struct timex {
|
||||||
#define ADJ_OFFSET 0x0001 /* time offset */
|
#define ADJ_OFFSET 0x0001 /* time offset */
|
||||||
#define ADJ_FREQUENCY 0x0002 /* frequency offset */
|
#define ADJ_FREQUENCY 0x0002 /* frequency offset */
|
||||||
#define ADJ_MAXERROR 0x0004 /* maximum time error */
|
#define ADJ_MAXERROR 0x0004 /* maximum time error */
|
||||||
|
#define ADJ_ESTERROR 0x0008 /* estimated time error */
|
||||||
#define ADJ_STATUS 0x0010 /* clock status */
|
#define ADJ_STATUS 0x0010 /* clock status */
|
||||||
#define ADJ_TIMECONST 0x0020 /* pll time constant */
|
#define ADJ_TIMECONST 0x0020 /* pll time constant */
|
||||||
#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
|
#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
|
||||||
|
|
|
@ -39,9 +39,10 @@
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
/* System clock frequency drivers */
|
/* System clock drivers */
|
||||||
static lcl_ReadFrequencyDriver drv_read_freq;
|
static lcl_ReadFrequencyDriver drv_read_freq;
|
||||||
static lcl_SetFrequencyDriver drv_set_freq;
|
static lcl_SetFrequencyDriver drv_set_freq;
|
||||||
|
static lcl_SetSyncStatusDriver drv_set_sync_status;
|
||||||
|
|
||||||
/* Current frequency as requested by the local module (in ppm) */
|
/* Current frequency as requested by the local module (in ppm) */
|
||||||
static double base_freq;
|
static double base_freq;
|
||||||
|
@ -270,6 +271,22 @@ apply_step_offset(double offset)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_sync_status(int synchronised, double est_error, double max_error)
|
||||||
|
{
|
||||||
|
double offset;
|
||||||
|
|
||||||
|
offset = fabs(offset_register);
|
||||||
|
if (est_error < offset)
|
||||||
|
est_error = offset;
|
||||||
|
max_error += offset;
|
||||||
|
|
||||||
|
if (drv_set_sync_status)
|
||||||
|
drv_set_sync_status(synchronised, est_error, max_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
void
|
void
|
||||||
SYS_Generic_CompleteFreqDriver(double max_set_freq_ppm, double max_set_freq_delay,
|
SYS_Generic_CompleteFreqDriver(double max_set_freq_ppm, double max_set_freq_delay,
|
||||||
lcl_ReadFrequencyDriver sys_read_freq,
|
lcl_ReadFrequencyDriver sys_read_freq,
|
||||||
|
@ -282,6 +299,7 @@ SYS_Generic_CompleteFreqDriver(double max_set_freq_ppm, double max_set_freq_dela
|
||||||
max_freq_change_delay = max_set_freq_delay * (1.0 + max_freq / 1.0e6);
|
max_freq_change_delay = max_set_freq_delay * (1.0 + max_freq / 1.0e6);
|
||||||
drv_read_freq = sys_read_freq;
|
drv_read_freq = sys_read_freq;
|
||||||
drv_set_freq = sys_set_freq;
|
drv_set_freq = sys_set_freq;
|
||||||
|
drv_set_sync_status = sys_set_sync_status;
|
||||||
|
|
||||||
base_freq = (*drv_read_freq)();
|
base_freq = (*drv_read_freq)();
|
||||||
slew_freq = 0.0;
|
slew_freq = 0.0;
|
||||||
|
@ -292,7 +310,7 @@ SYS_Generic_CompleteFreqDriver(double max_set_freq_ppm, double max_set_freq_dela
|
||||||
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
lcl_RegisterSystemDrivers(read_frequency, set_frequency,
|
||||||
accrue_offset, sys_apply_step_offset ?
|
accrue_offset, sys_apply_step_offset ?
|
||||||
sys_apply_step_offset : apply_step_offset,
|
sys_apply_step_offset : apply_step_offset,
|
||||||
offset_convert, sys_set_leap, NULL);
|
offset_convert, sys_set_leap, set_sync_status);
|
||||||
|
|
||||||
LCL_AddParameterChangeHandler(handle_step, NULL);
|
LCL_AddParameterChangeHandler(handle_step, NULL);
|
||||||
}
|
}
|
||||||
|
|
30
sys_linux.c
30
sys_linux.c
|
@ -58,6 +58,9 @@ int LockAll = 0;
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "wrap_adjtimex.h"
|
#include "wrap_adjtimex.h"
|
||||||
|
|
||||||
|
/* The threshold for adjtimex maxerror when the kernel sets the UNSYNC flag */
|
||||||
|
#define UNSYNC_MAXERROR 16.0
|
||||||
|
|
||||||
/* This is the uncompensated system tick value */
|
/* This is the uncompensated system tick value */
|
||||||
static int nominal_tick;
|
static int nominal_tick;
|
||||||
|
|
||||||
|
@ -181,6 +184,29 @@ set_leap(int leap)
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_sync_status(int synchronised, double est_error, double max_error)
|
||||||
|
{
|
||||||
|
if (synchronised) {
|
||||||
|
if (est_error > UNSYNC_MAXERROR)
|
||||||
|
est_error = UNSYNC_MAXERROR;
|
||||||
|
if (max_error >= UNSYNC_MAXERROR) {
|
||||||
|
max_error = UNSYNC_MAXERROR;
|
||||||
|
synchronised = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
est_error = max_error = UNSYNC_MAXERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the UNSYNC flag only if rtcsync is enabled */
|
||||||
|
if (!CNF_GetRtcSync())
|
||||||
|
synchronised = 0;
|
||||||
|
|
||||||
|
TMX_SetSync(synchronised, est_error, max_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
|
||||||
/* Estimate the value of USER_HZ given the value of txc.tick that chronyd finds when
|
/* Estimate the value of USER_HZ given the value of txc.tick that chronyd finds when
|
||||||
* it starts. The only credible values are 100 (Linux/x86) or powers of 2.
|
* it starts. The only credible values are 100 (Linux/x86) or powers of 2.
|
||||||
* Also, the bounds checking inside the kernel's adjtimex system call enforces
|
* Also, the bounds checking inside the kernel's adjtimex system call enforces
|
||||||
|
@ -334,13 +360,11 @@ SYS_Linux_Initialise(void)
|
||||||
have_setoffset = 0;
|
have_setoffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TMX_SetSync(CNF_GetRtcSync());
|
|
||||||
|
|
||||||
SYS_Generic_CompleteFreqDriver(1.0e6 * max_tick_bias / nominal_tick,
|
SYS_Generic_CompleteFreqDriver(1.0e6 * max_tick_bias / nominal_tick,
|
||||||
1.0 / tick_update_hz,
|
1.0 / tick_update_hz,
|
||||||
read_frequency, set_frequency,
|
read_frequency, set_frequency,
|
||||||
have_setoffset ? apply_step_offset : NULL,
|
have_setoffset ? apply_step_offset : NULL,
|
||||||
set_leap, NULL);
|
set_leap, set_sync_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
|
@ -68,19 +68,11 @@ TMX_SetFrequency(double *freq, long tick)
|
||||||
{
|
{
|
||||||
struct timex txc;
|
struct timex txc;
|
||||||
|
|
||||||
txc.modes = ADJ_TICK | ADJ_FREQUENCY | ADJ_STATUS;
|
txc.modes = ADJ_TICK | ADJ_FREQUENCY;
|
||||||
|
|
||||||
txc.freq = (long)(*freq * (double)(1 << SHIFT_USEC));
|
txc.freq = (long)(*freq * (double)(1 << SHIFT_USEC));
|
||||||
*freq = txc.freq / (double)(1 << SHIFT_USEC);
|
*freq = txc.freq / (double)(1 << SHIFT_USEC);
|
||||||
txc.tick = tick;
|
txc.tick = tick;
|
||||||
txc.status = status;
|
|
||||||
|
|
||||||
if (!(status & STA_UNSYNC)) {
|
|
||||||
/* maxerror has to be reset periodically to prevent kernel
|
|
||||||
from enabling UNSYNC flag */
|
|
||||||
txc.modes |= ADJ_MAXERROR;
|
|
||||||
txc.maxerror = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return adjtimex(&txc);
|
return adjtimex(&txc);
|
||||||
}
|
}
|
||||||
|
@ -161,7 +153,7 @@ TMX_SetLeap(int leap)
|
||||||
return adjtimex(&txc);
|
return adjtimex(&txc);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TMX_SetSync(int sync)
|
int TMX_SetSync(int sync, double est_error, double max_error)
|
||||||
{
|
{
|
||||||
struct timex txc;
|
struct timex txc;
|
||||||
|
|
||||||
|
@ -171,8 +163,10 @@ int TMX_SetSync(int sync)
|
||||||
status |= STA_UNSYNC;
|
status |= STA_UNSYNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
txc.modes = ADJ_STATUS;
|
txc.modes = ADJ_STATUS | ADJ_ESTERROR | ADJ_MAXERROR;
|
||||||
txc.status = status;
|
txc.status = status;
|
||||||
|
txc.esterror = est_error * 1.0e6;
|
||||||
|
txc.maxerror = max_error * 1.0e6;
|
||||||
|
|
||||||
return adjtimex(&txc);
|
return adjtimex(&txc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ int TMX_SetFrequency(double *freq, long tick);
|
||||||
int TMX_GetFrequency(double *freq, long *tick);
|
int TMX_GetFrequency(double *freq, long *tick);
|
||||||
int TMX_ReadCurrentParams(struct tmx_params *params);
|
int TMX_ReadCurrentParams(struct tmx_params *params);
|
||||||
int TMX_SetLeap(int leap);
|
int TMX_SetLeap(int leap);
|
||||||
int TMX_SetSync(int sync);
|
int TMX_SetSync(int sync, double est_error, double max_error);
|
||||||
int TMX_TestStepOffset(void);
|
int TMX_TestStepOffset(void);
|
||||||
int TMX_ApplyStepOffset(double offset);
|
int TMX_ApplyStepOffset(double offset);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue