reference: improve check for close leap second
Improve the check to work with the actual timestamp of the leap second instead of the closest midnight and don't turn it off on the leap timeout. Also allow sample times to be checked in addition to the system time and NTP time to avoid accumulation of samples mixing pre-leap and post-leap timestamps (causing error of +/-0.5 or +/-1.0 seconds).
This commit is contained in:
parent
a6f2a613f3
commit
c687224a11
3 changed files with 24 additions and 16 deletions
30
reference.c
30
reference.c
|
@ -112,6 +112,9 @@ static void update_drift_file(double, double);
|
|||
/* Leap second handling mode */
|
||||
static REF_LeapMode leap_mode;
|
||||
|
||||
/* Time of UTC midnight of the upcoming or previous leap second */
|
||||
static time_t leap_when;
|
||||
|
||||
/* Flag indicating the clock was recently corrected for leap second and it may
|
||||
not have correct time yet (missing 23:59:60 in the UTC time scale) */
|
||||
static int leap_in_progress;
|
||||
|
@ -246,6 +249,7 @@ REF_Initialise(void)
|
|||
enable_local_stratum = CNF_AllowLocalReference(&local_stratum, &local_orphan, &local_distance);
|
||||
UTI_ZeroTimespec(&local_ref_time);
|
||||
|
||||
leap_when = 0;
|
||||
leap_timeout_id = 0;
|
||||
leap_in_progress = 0;
|
||||
leap_mode = CNF_GetLeapSecMode();
|
||||
|
@ -720,10 +724,12 @@ set_leap_timeout(time_t now)
|
|||
if (!our_leap_sec)
|
||||
return;
|
||||
|
||||
leap_when = (now / (24 * 3600) + 1) * (24 * 3600);
|
||||
|
||||
/* Insert leap second at 0:00:00 UTC, delete at 23:59:59 UTC. If the clock
|
||||
will be corrected by the system, timeout slightly sooner to be sure it
|
||||
will happen before the system correction. */
|
||||
when.tv_sec = (now / (24 * 3600) + 1) * (24 * 3600);
|
||||
when.tv_sec = leap_when;
|
||||
when.tv_nsec = 0;
|
||||
if (our_leap_sec < 0)
|
||||
when.tv_sec--;
|
||||
|
@ -767,7 +773,7 @@ update_leap_status(NTP_Leap leap, time_t now, int reset)
|
|||
}
|
||||
|
||||
if ((leap_sec != our_leap_sec || tai_offset != our_tai_offset)
|
||||
&& !REF_IsLeapSecondClose()) {
|
||||
&& !REF_IsLeapSecondClose(NULL, 0.0)) {
|
||||
our_leap_sec = leap_sec;
|
||||
our_tai_offset = tai_offset;
|
||||
|
||||
|
@ -1324,22 +1330,24 @@ REF_DisableLocal(void)
|
|||
|
||||
#define LEAP_SECOND_CLOSE 5
|
||||
|
||||
int REF_IsLeapSecondClose(void)
|
||||
static int
|
||||
is_leap_close(time_t t)
|
||||
{
|
||||
return t >= leap_when - LEAP_SECOND_CLOSE && t < leap_when + LEAP_SECOND_CLOSE;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
int REF_IsLeapSecondClose(struct timespec *ts, double offset)
|
||||
{
|
||||
struct timespec now, now_raw;
|
||||
time_t t;
|
||||
|
||||
if (!our_leap_sec)
|
||||
return 0;
|
||||
|
||||
SCH_GetLastEventTime(&now, NULL, &now_raw);
|
||||
|
||||
t = now.tv_sec > 0 ? now.tv_sec : -now.tv_sec;
|
||||
if ((t + LEAP_SECOND_CLOSE) % (24 * 3600) < 2 * LEAP_SECOND_CLOSE)
|
||||
if (is_leap_close(now.tv_sec) || is_leap_close(now_raw.tv_sec))
|
||||
return 1;
|
||||
|
||||
t = now_raw.tv_sec > 0 ? now_raw.tv_sec : -now_raw.tv_sec;
|
||||
if ((t + LEAP_SECOND_CLOSE) % (24 * 3600) < 2 * LEAP_SECOND_CLOSE)
|
||||
if (ts && (is_leap_close(ts->tv_sec) || is_leap_close(ts->tv_sec + offset)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -184,9 +184,9 @@ extern void REF_ModifyMakestep(int limit, double threshold);
|
|||
extern void REF_EnableLocal(int stratum, double distance, int orphan);
|
||||
extern void REF_DisableLocal(void);
|
||||
|
||||
/* Check if current raw or cooked time is close to a leap second
|
||||
and is better to discard any measurements */
|
||||
extern int REF_IsLeapSecondClose(void);
|
||||
/* Check if either of the current raw and cooked time, and optionally a
|
||||
provided timestamp with an offset, is close to a leap second */
|
||||
extern int REF_IsLeapSecondClose(struct timespec *ts, double offset);
|
||||
|
||||
/* Return TAI-UTC offset corresponding to a time in UTC if available */
|
||||
extern int REF_GetTaiOffset(struct timespec *ts);
|
||||
|
|
|
@ -361,7 +361,7 @@ get_leap_status(void)
|
|||
void
|
||||
SRC_SetLeapStatus(SRC_Instance inst, NTP_Leap leap)
|
||||
{
|
||||
if (REF_IsLeapSecondClose())
|
||||
if (REF_IsLeapSecondClose(NULL, 0.0))
|
||||
return;
|
||||
|
||||
inst->leap = leap;
|
||||
|
@ -390,7 +390,7 @@ SRC_AccumulateSample(SRC_Instance inst, NTP_Sample *sample)
|
|||
source_to_string(inst), UTI_TimespecToString(&sample->time), -sample->offset,
|
||||
sample->root_delay, sample->root_dispersion, sample->stratum);
|
||||
|
||||
if (REF_IsLeapSecondClose()) {
|
||||
if (REF_IsLeapSecondClose(&sample->time, sample->offset)) {
|
||||
LOG(LOGS_INFO, "Dropping sample around leap second");
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue