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
Jiri Benc 2014-06-11 21:35:12 +02:00 committed by Richard Cochran
parent a1bee8fbb7
commit 423eb54530
1 changed files with 55 additions and 16 deletions

View File

@ -60,7 +60,9 @@
#define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC) #define PMC_UPDATE_INTERVAL (60 * NS_PER_SEC)
struct clock; 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) static clockid_t clock_open(char *device)
{ {
@ -181,13 +183,14 @@ static void update_clock_stats(struct clock *clock,
stats_reset(clock->delay_stats); stats_reset(clock->delay_stats);
} }
static void update_clock(struct clock *clock, static void update_clock(struct clock *clock, clockid_t src,
int64_t offset, uint64_t ts, int64_t delay) int64_t offset, uint64_t ts, int64_t delay,
int do_leap)
{ {
enum servo_state state; enum servo_state state;
double ppb; double ppb;
if (update_sync_offset(clock, offset, ts)) if (clock_handle_leap(clock, src, offset, ts, do_leap))
return; return;
if (clock->sync_offset_direction) 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; int64_t pps_offset, phc_offset, phc_delay;
uint64_t pps_ts, phc_ts; uint64_t pps_ts, phc_ts;
int do_leap;
clock->source_label = "pps"; clock->source_label = "pps";
@ -304,7 +308,10 @@ static int do_pps_loop(struct clock *clock, int fd,
pps_offset = pps_ts - phc_ts; 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); close(fd);
return 0; return 0;
@ -316,6 +323,7 @@ static int do_sysoff_loop(struct clock *clock, clockid_t src,
uint64_t ts; uint64_t ts;
int64_t offset, delay; int64_t offset, delay;
int err = 0, fd = CLOCKID_TO_FD(src); int err = 0, fd = CLOCKID_TO_FD(src);
int do_leap;
clock->source_label = "sys"; clock->source_label = "sys";
@ -325,7 +333,10 @@ static int do_sysoff_loop(struct clock *clock, clockid_t src,
err = -1; err = -1;
break; 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; return err;
} }
@ -335,6 +346,7 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
{ {
uint64_t ts; uint64_t ts;
int64_t offset, delay; int64_t offset, delay;
int do_leap;
clock->source_label = "phc"; clock->source_label = "phc";
@ -344,7 +356,10 @@ static int do_phc_loop(struct clock *clock, clockid_t src,
&offset, &ts, &delay)) { &offset, &ts, &delay)) {
continue; 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; return 0;
} }
@ -495,10 +510,19 @@ static void close_pmc(struct clock *clock)
clock->pmc = NULL; 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; 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 && if (clock->pmc &&
!(ts > clock->pmc_last_update && !(ts > clock->pmc_last_update &&
ts - clock->pmc_last_update < PMC_UPDATE_INTERVAL)) { 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) if (!clock->leap && !clock->leap_set)
return 0; 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 /* 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. */ it, as it is the clock which will include the leap second. */
if (clock->clkid != CLOCK_REALTIME) { if (src == CLOCK_REALTIME) {
struct timespec tp; struct timespec tp;
if (clock_gettime(CLOCK_REALTIME, &tp)) { if (clock_gettime(CLOCK_REALTIME, &tp)) {
pr_err("failed to read clock: %m"); 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. */ /* Suspend clock updates in the last second before midnight. */
if (is_utc_ambiguous(ts)) { if (is_utc_ambiguous(ts)) {
pr_info("clock update suspended due to leap second"); pr_info("clock update suspended due to leap second");
return -1; return 1;
} }
clock_leap = leap_second_status(ts, clock->leap_set, if (do_leap) {
&clock->leap, &clock->sync_offset);
if (clock->leap_set != clock_leap) {
/* Only the system clock can leap. */ /* Only the system clock can leap. */
if (clock->clkid == CLOCK_REALTIME && clock->kernel_leap) if (clock->clkid == CLOCK_REALTIME && clock->kernel_leap)
sysclk_set_leap(clock_leap); sysclk_set_leap(clock->leap_set);
clock->leap_set = clock_leap;
} }
return 0; return 0;