phc2sys: store information about clocks being UTC or TAI

For now, only CLOCK_REALTIME can be UTC. This may stay this way forever but
now we have a clean separation between codepaths where CLOCK_REALTIME is
required and codepaths any UTC clock should take.

The main motiviation behind this change is removal of sync_offset_direction.
It has to be computed on the fly based on the source and destination when we
have multiple clocks supported and automatic following of ptp4l state
changes implemented.

Signed-off-by: Jiri Benc <jbenc@redhat.com>
master
Jiri Benc 2014-06-11 21:35:14 +02:00 committed by Richard Cochran
parent be4251a552
commit 78aaef8a1a
1 changed files with 29 additions and 31 deletions

View File

@ -130,6 +130,7 @@ struct clock {
LIST_ENTRY(clock) list; LIST_ENTRY(clock) list;
clockid_t clkid; clockid_t clkid;
int sysoff_supported; int sysoff_supported;
int is_utc;
struct servo *servo; struct servo *servo;
enum servo_state servo_state; enum servo_state servo_state;
const char *source_label; const char *source_label;
@ -146,7 +147,7 @@ struct node {
int phc_readings; int phc_readings;
double phc_interval; double phc_interval;
int sync_offset; int sync_offset;
int sync_offset_direction; int forced_sync_offset;
int leap; int leap;
int leap_set; int leap_set;
int kernel_leap; int kernel_leap;
@ -161,6 +162,15 @@ static int update_sync_offset(struct node *node);
static int clock_handle_leap(struct node *node, struct clock *clock, static int clock_handle_leap(struct node *node, struct clock *clock,
int64_t offset, uint64_t ts, int do_leap); int64_t offset, uint64_t ts, int do_leap);
static int64_t get_sync_offset(struct node *node, struct clock *dst)
{
int direction = node->forced_sync_offset;
if (!direction)
direction = dst->is_utc - node->master->is_utc;
return (int64_t)node->sync_offset * NS_PER_SEC * direction;
}
static void update_clock_stats(struct clock *clock, unsigned int max_count, static void update_clock_stats(struct clock *clock, unsigned int max_count,
int64_t offset, double freq, int64_t delay) int64_t offset, double freq, int64_t delay)
{ {
@ -206,9 +216,7 @@ static void update_clock(struct node *node, struct clock *clock,
if (clock_handle_leap(node, clock, offset, ts, do_leap)) if (clock_handle_leap(node, clock, offset, ts, do_leap))
return; return;
if (node->sync_offset_direction) offset += get_sync_offset(node, clock);
offset += node->sync_offset * NS_PER_SEC *
node->sync_offset_direction;
if (clock->sanity_check && clockcheck_sample(clock->sanity_check, ts)) if (clock->sanity_check && clockcheck_sample(clock->sanity_check, ts))
servo_reset(clock->servo); servo_reset(clock->servo);
@ -290,7 +298,7 @@ static int do_pps_loop(struct node *node, struct clock *clock, int fd)
if (src == CLOCK_INVALID) { if (src == CLOCK_INVALID) {
/* The sync offset can't be applied with PPS alone. */ /* The sync offset can't be applied with PPS alone. */
node->sync_offset_direction = 0; node->sync_offset = 0;
} else { } else {
enable_pps_output(node->master->clkid); enable_pps_output(node->master->clkid);
} }
@ -558,15 +566,14 @@ static int clock_handle_leap(struct node *node, struct clock *clock,
if (!node->leap && !do_leap) if (!node->leap && !do_leap)
return 0; return 0;
if (clock->clkid != CLOCK_REALTIME && if (clock->is_utc == node->master->is_utc)
node->master->clkid != CLOCK_REALTIME)
return 0; 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 (node->master->clkid == CLOCK_REALTIME) { if (node->master->is_utc) {
struct timespec tp; struct timespec tp;
if (clock_gettime(CLOCK_REALTIME, &tp)) { if (clock_gettime(node->master->clkid, &tp)) {
pr_err("failed to read clock: %m"); pr_err("failed to read clock: %m");
return -1; return -1;
} }
@ -575,11 +582,8 @@ static int clock_handle_leap(struct node *node, struct clock *clock,
/* If the clock will be stepped, the time stamp has to be the /* If the clock will be stepped, the time stamp has to be the
target time. Ignore possible 1 second error in UTC offset. */ target time. Ignore possible 1 second error in UTC offset. */
if (clock->clkid == CLOCK_REALTIME && if (clock->is_utc && clock->servo_state == SERVO_UNLOCKED)
clock->servo_state == SERVO_UNLOCKED) { ts -= offset + get_sync_offset(node, clock);
ts -= offset + node->sync_offset * NS_PER_SEC *
node->sync_offset_direction;
}
/* 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)) {
@ -610,10 +614,12 @@ static int clock_add(struct node *node, clockid_t clkid)
c->clkid = clkid; c->clkid = clkid;
c->servo_state = SERVO_UNLOCKED; c->servo_state = SERVO_UNLOCKED;
if (c->clkid == CLOCK_REALTIME) if (c->clkid == CLOCK_REALTIME) {
c->source_label = "sys"; c->source_label = "sys";
else c->is_utc = 1;
} else {
c->source_label = "phc"; c->source_label = "phc";
}
if (node->stats_max_count > 0) { if (node->stats_max_count > 0) {
c->offset_stats = stats_create(); c->offset_stats = stats_create();
@ -698,7 +704,7 @@ int main(int argc, char *argv[])
clockid_t src = CLOCK_INVALID; clockid_t src = CLOCK_INVALID;
clockid_t dst = CLOCK_REALTIME; clockid_t dst = CLOCK_REALTIME;
int c, domain_number = 0, pps_fd = -1; int c, domain_number = 0, pps_fd = -1;
int r, wait_sync = 0, forced_sync_offset = 0; int r, wait_sync = 0;
int print_level = LOG_INFO, use_syslog = 1, verbose = 0; int print_level = LOG_INFO, use_syslog = 1, verbose = 0;
double phc_rate; double phc_rate;
struct node node = { struct node node = {
@ -779,8 +785,7 @@ int main(int argc, char *argv[])
if (get_arg_val_i(c, optarg, &node.sync_offset, if (get_arg_val_i(c, optarg, &node.sync_offset,
INT_MIN, INT_MAX)) INT_MIN, INT_MAX))
return -1; return -1;
node.sync_offset_direction = -1; node.forced_sync_offset = -1;
forced_sync_offset = 1;
break; break;
case 'L': case 'L':
if (get_arg_val_i(c, optarg, &node.sanity_freq_limit, 0, INT_MAX)) if (get_arg_val_i(c, optarg, &node.sanity_freq_limit, 0, INT_MAX))
@ -841,7 +846,7 @@ int main(int argc, char *argv[])
goto bad_usage; goto bad_usage;
} }
if (!wait_sync && !forced_sync_offset) { if (!wait_sync && !node.forced_sync_offset) {
fprintf(stderr, fprintf(stderr,
"time offset must be specified using -w or -O\n"); "time offset must be specified using -w or -O\n");
goto bad_usage; goto bad_usage;
@ -870,24 +875,17 @@ int main(int argc, char *argv[])
pr_notice("Waiting for ptp4l..."); pr_notice("Waiting for ptp4l...");
} }
if (!forced_sync_offset) { if (!node.forced_sync_offset) {
r = run_pmc_get_utc_offset(&node, 1000); r = run_pmc_get_utc_offset(&node, 1000);
if (r <= 0) { if (r <= 0) {
pr_err("failed to get UTC offset"); pr_err("failed to get UTC offset");
return -1; return -1;
} }
if (src != CLOCK_REALTIME &&
dst == CLOCK_REALTIME)
node.sync_offset_direction = 1;
else if (src == CLOCK_REALTIME &&
dst != CLOCK_REALTIME)
node.sync_offset_direction = -1;
else
node.sync_offset_direction = 0;
} }
if (forced_sync_offset || !node.sync_offset_direction) if (node.forced_sync_offset ||
(src != CLOCK_REALTIME && dst != CLOCK_REALTIME) ||
src == CLOCK_INVALID)
close_pmc(&node); close_pmc(&node);
} }