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>
This commit is contained in:
		
							parent
							
								
									be4251a552
								
							
						
					
					
						commit
						78aaef8a1a
					
				
							
								
								
									
										60
									
								
								phc2sys.c
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								phc2sys.c
									
									
									
									
									
								
							@ -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);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user