linreg: Handle leap second gracefully.
When leap second is inserted/deleted to the reference time, adjust the reference point as if the clock was stepped in the opposite direction to keep the slope and error statistics valid and correct the offset gracefully. Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>master
parent
bc84b88053
commit
97f72ceecc
17
linreg.c
17
linreg.c
|
@ -76,6 +76,8 @@ struct linreg_servo {
|
|||
double update_interval;
|
||||
/* Current ratio between remote and local frequency */
|
||||
double frequency_ratio;
|
||||
/* Upcoming leap second */
|
||||
int leap;
|
||||
};
|
||||
|
||||
static void linreg_destroy(struct servo *servo)
|
||||
|
@ -305,6 +307,20 @@ static double linreg_rate_ratio(struct servo *servo)
|
|||
return s->frequency_ratio;
|
||||
}
|
||||
|
||||
static void linreg_leap(struct servo *servo, int leap)
|
||||
{
|
||||
struct linreg_servo *s = container_of(servo, struct linreg_servo, servo);
|
||||
|
||||
/*
|
||||
* Move reference when leap second is applied to the reference
|
||||
* time as if the clock was stepped in the opposite direction
|
||||
*/
|
||||
if (s->leap && !leap)
|
||||
move_reference(s, 0, s->leap * 1000000000);
|
||||
|
||||
s->leap = leap;
|
||||
}
|
||||
|
||||
struct servo *linreg_servo_create(int fadj)
|
||||
{
|
||||
struct linreg_servo *s;
|
||||
|
@ -318,6 +334,7 @@ struct servo *linreg_servo_create(int fadj)
|
|||
s->servo.sync_interval = linreg_sync_interval;
|
||||
s->servo.reset = linreg_reset;
|
||||
s->servo.rate_ratio = linreg_rate_ratio;
|
||||
s->servo.leap = linreg_leap;
|
||||
|
||||
s->clock_freq = -fadj;
|
||||
s->frequency_ratio = 1.0;
|
||||
|
|
Loading…
Reference in New Issue