phc2sys: split update_sync_offset
Split the generic (global) part of update_sync_offset and the part that affects individual clocks. This is in preparation for phc2sys handling synchronization of more clocks. Signed-off-by: Jiri Benc <jbenc@redhat.com>master
parent
a1bee8fbb7
commit
423eb54530
71
phc2sys.c
71
phc2sys.c
|
@ -60,7 +60,9 @@
|
|||
#define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
|
||||
|
||||
struct clock;
|
||||
static int update_sync_offset(struct clock *clock, int64_t offset, uint64_t ts);
|
||||
static int update_sync_offset(struct clock *clock);
|
||||
static int clock_handle_leap(struct clock *clock, clockid_t src,
|
||||
int64_t offset, uint64_t ts, int do_leap);
|
||||
|
||||
static clockid_t clock_open(char *device)
|
||||
{
|
||||
|
@ -181,13 +183,14 @@ static void update_clock_stats(struct clock *clock,
|
|||
stats_reset(clock->delay_stats);
|
||||
}
|
||||
|
||||
static void update_clock(struct clock *clock,
|
||||
int64_t offset, uint64_t ts, int64_t delay)
|
||||
static void update_clock(struct clock *clock, clockid_t src,
|
||||
int64_t offset, uint64_t ts, int64_t delay,
|
||||
int do_leap)
|
||||
{
|
||||
enum servo_state state;
|
||||
double ppb;
|
||||
|
||||
if (update_sync_offset(clock, offset, ts))
|
||||
if (clock_handle_leap(clock, src, offset, ts, do_leap))
|
||||
return;
|
||||
|
||||
if (clock->sync_offset_direction)
|
||||
|
@ -268,6 +271,7 @@ static int do_pps_loop(struct clock *clock, int fd,
|
|||
{
|
||||
int64_t pps_offset, phc_offset, phc_delay;
|
||||
uint64_t pps_ts, phc_ts;
|
||||
int do_leap;
|
||||
|
||||
clock->source_label = "pps";
|
||||
|
||||
|
@ -304,7 +308,10 @@ static int do_pps_loop(struct clock *clock, int fd,
|
|||
pps_offset = pps_ts - phc_ts;
|
||||
}
|
||||
|
||||
update_clock(clock, pps_offset, pps_ts, -1);
|
||||
do_leap = update_sync_offset(clock);
|
||||
if (do_leap <= 0)
|
||||
continue;
|
||||
update_clock(clock, src, pps_offset, pps_ts, -1, do_leap);
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
|
@ -316,6 +323,7 @@ static int do_sysoff_loop(struct clock *clock, clockid_t src,
|
|||
uint64_t ts;
|
||||
int64_t offset, delay;
|
||||
int err = 0, fd = CLOCKID_TO_FD(src);
|
||||
int do_leap;
|
||||
|
||||
clock->source_label = "sys";
|
||||
|
||||
|
@ -325,7 +333,10 @@ static int do_sysoff_loop(struct clock *clock, clockid_t src,
|
|||
err = -1;
|
||||
break;
|
||||
}
|
||||
update_clock(clock, offset, ts, delay);
|
||||
do_leap = update_sync_offset(clock);
|
||||
if (do_leap <= 0)
|
||||
continue;
|
||||
update_clock(clock, src, offset, ts, delay, do_leap);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -335,6 +346,7 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
|
|||
{
|
||||
uint64_t ts;
|
||||
int64_t offset, delay;
|
||||
int do_leap;
|
||||
|
||||
clock->source_label = "phc";
|
||||
|
||||
|
@ -344,7 +356,10 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
|
|||
&offset, &ts, &delay)) {
|
||||
continue;
|
||||
}
|
||||
update_clock(clock, offset, ts, delay);
|
||||
do_leap = update_sync_offset(clock);
|
||||
if (do_leap <= 0)
|
||||
continue;
|
||||
update_clock(clock, src, offset, ts, delay, do_leap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -495,10 +510,19 @@ static void close_pmc(struct clock *clock)
|
|||
clock->pmc = NULL;
|
||||
}
|
||||
|
||||
static int update_sync_offset(struct clock *clock, int64_t offset, uint64_t ts)
|
||||
/* Returns: -1 in case of error, 0 for normal sync, 1 to leap clock */
|
||||
static int update_sync_offset(struct clock *clock)
|
||||
{
|
||||
struct timespec tp;
|
||||
uint64_t ts;
|
||||
int clock_leap;
|
||||
|
||||
if (clock_gettime(CLOCK_REALTIME, &tp)) {
|
||||
pr_err("failed to read clock: %m");
|
||||
return -1;
|
||||
}
|
||||
ts = tp.tv_sec * NS_PER_SEC + tp.tv_nsec;
|
||||
|
||||
if (clock->pmc &&
|
||||
!(ts > clock->pmc_last_update &&
|
||||
ts - clock->pmc_last_update < PMC_UPDATE_INTERVAL)) {
|
||||
|
@ -511,9 +535,28 @@ static int update_sync_offset(struct clock *clock, int64_t offset, uint64_t ts)
|
|||
if (!clock->leap && !clock->leap_set)
|
||||
return 0;
|
||||
|
||||
clock_leap = leap_second_status(ts, clock->leap_set,
|
||||
&clock->leap, &clock->sync_offset);
|
||||
if (clock->leap_set != clock_leap) {
|
||||
clock->leap_set = clock_leap;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns: non-zero to skip clock update */
|
||||
static int clock_handle_leap(struct clock *clock, clockid_t src,
|
||||
int64_t offset, uint64_t ts, int do_leap)
|
||||
{
|
||||
if (!clock->leap && !do_leap)
|
||||
return 0;
|
||||
|
||||
if (clock->clkid != CLOCK_REALTIME && src != CLOCK_REALTIME)
|
||||
return 0;
|
||||
|
||||
/* If the system clock is the master clock, get a time stamp from
|
||||
it, as it is the clock which will include the leap second. */
|
||||
if (clock->clkid != CLOCK_REALTIME) {
|
||||
if (src == CLOCK_REALTIME) {
|
||||
struct timespec tp;
|
||||
if (clock_gettime(CLOCK_REALTIME, &tp)) {
|
||||
pr_err("failed to read clock: %m");
|
||||
|
@ -533,17 +576,13 @@ static int update_sync_offset(struct clock *clock, int64_t offset, uint64_t ts)
|
|||
/* Suspend clock updates in the last second before midnight. */
|
||||
if (is_utc_ambiguous(ts)) {
|
||||
pr_info("clock update suspended due to leap second");
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
clock_leap = leap_second_status(ts, clock->leap_set,
|
||||
&clock->leap, &clock->sync_offset);
|
||||
|
||||
if (clock->leap_set != clock_leap) {
|
||||
if (do_leap) {
|
||||
/* Only the system clock can leap. */
|
||||
if (clock->clkid == CLOCK_REALTIME && clock->kernel_leap)
|
||||
sysclk_set_leap(clock_leap);
|
||||
clock->leap_set = clock_leap;
|
||||
sysclk_set_leap(clock->leap_set);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue