Skip to contentSkip to conversation

hwclock: new --compare option

RFE Ondrej Oprala 2 participants 2 messages Aug 29, 2012 – Sep 11, 2012 Util-Linux package

lore
Share & tools
lore
#0 lore raw

Hi,
Here's my patch and proposal to add a compare option to hwclock. The idea is that it would perform similarly to adjtimex --compare.

have a nice day,
Ondrej.

Quoted 1 line

From 3a5494a1c32e2698de0508cec70149bed8149032 Mon Sep 17 00:00:00 2001

From: Ondrej Oprala <[email protected]>
Date: Wed, 29 Aug 2012 18:11:15 +0200
Subject: [PATCH] hwclock: add a new --compare option

The new option imitates adjtimex -c functionality and outputs the drift in 10 second intervals.

---
 sys-utils/hwclock.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 71 insertions(+), 4 deletions(-)
sys-utils/hwclock.c +71 -4
index e25546d..407ac8a 100644
@@ -1337,6 +1337,61 @@ manipulate_epoch(const bool getepoch,
 # endif		/* __alpha__ */
 #endif		/* __linux__ */
 
+/*
+ * Compare the system and CMOS time and output the drift
+ * in 10 second intervals.
+ */
+static int compare_clock (const bool utc, const bool local_opt)
+{
+	struct tm tm;
+	struct timeval tv;
+	struct adjtime adjtime;
+	double time1_sys, time2_sys;
+	time_t time1_hw, time2_hw;
+	bool hclock_valid = FALSE;
+
+	/* dummy call for increased precision */
+	gettimeofday(&tv, NULL);
+
+	if (read_adjtime(&adjtime))
+		return 1;
+	bool universal = hw_clock_is_utc(utc, local_opt, adjtime);
+  ur->get_permissions();
+
+	synchronize_to_clock_tick();
+	ur->read_hardware_clock(&tm);
+
+	gettimeofday(&tv, NULL);
+	time1_sys = tv.tv_sec + tv.tv_usec / 1000000.0;
+
+	mktime_tz(tm, universal, &hclock_valid, &time1_hw);
+
+  bool first_pass = TRUE;
+
+	while (TRUE)
+	{
+		synchronize_to_clock_tick();
+		ur->read_hardware_clock(&tm);
+
+		gettimeofday(&tv, NULL);
+		time2_sys = tv.tv_sec + tv.tv_usec / 1000000.0;
+
+		mktime_tz(tm, universal, &hclock_valid, &time2_hw);
+
+		double res = ((time1_hw - time1_sys) - (time2_hw - time2_sys))
+				/ (time2_hw - time1_hw);
+
+		if(!first_pass)
+			printf ("sysclock/RTC frequency offset: %.0f ppm (%.0f ticks)\n",
+				res * 1e6, res *1e4);
+		else {
+			first_pass = FALSE;
+			printf ("sysclock/RTC frequency offset:    ppm (   ticks)\n");
+		}
+		sleep(10);
+	}
+}
+
 static void out_version(void)
 {
 	printf(_("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING);
@@ -1370,7 +1425,8 @@ static void usage(const char *fmt, ...)
 		" -w, --systohc        set the hardware clock from the current system time\n"
 		"     --systz          set the system time based on the current timezone\n"
 		"     --adjust         adjust the RTC to account for systematic drift since\n"
-		"                        the clock was last set or adjusted\n"), usageto);
+		"                        the clock was last set or adjusted\n"
+		" -c  --compare        periodically compare the system clock with the CMOS clock\n"), usageto);
 #ifdef __linux__
 	fputs(_("     --getepoch       print out the kernel's hardware clock epoch value\n"
 		"     --setepoch       set the kernel's hardware clock epoch value to the \n"
@@ -1438,7 +1494,7 @@ int main(int argc, char **argv)
 	/* Variables set by various options; show may also be set later */
 	/* The options debug, badyear and epoch_option are global */
 	bool show, set, systohc, hctosys, systz, adjust, getepoch, setepoch,
-	    predict;
+	    predict, compare;
 	bool utc, testing, local_opt, noadjfile, directisa;
 	char *date_opt;
 #ifdef __alpha__
@@ -1463,6 +1519,7 @@ int main(int argc, char **argv)
 
 	static const struct option longopts[] = {
 		{"adjust",	0, 0, 'a'},
+		{"compare",	0, 0, 'c'},
 		{"help",	0, 0, 'h'},
 		{"show",	0, 0, 'r'},
 		{"hctosys",	0, 0, 's'},
@@ -1540,7 +1597,7 @@ int main(int argc, char **argv)
 
 	/* Set option defaults */
 	show = set = systohc = hctosys = systz = adjust = noadjfile = predict =
-	    FALSE;
+	    compare = FALSE;
 	getepoch = setepoch = utc = local_opt = directisa = testing = debug = FALSE;
 #ifdef __alpha__
 	ARCconsole = Jensen = SRM = funky_toy = badyear = FALSE;
@@ -1548,7 +1605,7 @@ int main(int argc, char **argv)
 	date_opt = NULL;
 
 	while ((c = getopt_long(argc, argv,
-				"?hvVDarsuwAJSFf:", longopts, NULL)) != -1) {
+				"?hvVDacrsuwAJSFf:", longopts, NULL)) != -1) {
 
 		err_exclusive_options(c, longopts, excl, excl_st);
 
@@ -1559,6 +1616,9 @@ int main(int argc, char **argv)
 		case 'a':
 			adjust = TRUE;
 			break;
+		case 'c':
+			compare = TRUE;
+			break;
 		case 'r':
 			show = TRUE;
 			break;
@@ -1733,6 +1793,13 @@ int main(int argc, char **argv)
 		}
 	}
 
+	if (compare) {
+		if (compare_clock(utc, local_opt))
+			hwclock_exit(EX_NOPERM);
+		else
+			hwclock_exit(EX_OK);
+	}
+
 	rc = manipulate_clock(show, adjust, noadjfile, set, set_time,
 			      hctosys, systohc, systz, startup_time, utc,
 			      local_opt, testing, predict);
Signature · 1 line
1.7.11.4
maintainer
#1 lore raw
Quoted 10 lines · Ondrej Oprala

From 3a5494a1c32e2698de0508cec70149bed8149032 Mon Sep 17 00:00:00 2001
From: Ondrej Oprala <[email protected]>
Date: Wed, 29 Aug 2012 18:11:15 +0200
Subject: [PATCH] hwclock: add a new --compare option

The new option imitates adjtimex -c functionality and outputs the drift in 10 second intervals.

---
 sys-utils/hwclock.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 71 insertions(+), 4 deletions(-)

Applied with some changes (I have added hw-time and system-time columns to the output), thanks.

Karel

Signature · 2 lines
 Karel Zak  <[email protected]>
 http://karelzak.blogspot.com