summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_rtc.c
diff options
context:
space:
mode:
authorjkim <jkim@FreeBSD.org>2010-08-12 17:17:05 +0000
committerjkim <jkim@FreeBSD.org>2010-08-12 17:17:05 +0000
commitf9341f06d7ef1504c22d8498de4139effecd1f33 (patch)
treec5631ec00d3fbc26ce5be0735cb9d007328c45b6 /sys/kern/subr_rtc.c
parent6c415f8b84db102df1fff3b142caeb1d26dfc68d (diff)
downloadFreeBSD-src-f9341f06d7ef1504c22d8498de4139effecd1f33.zip
FreeBSD-src-f9341f06d7ef1504c22d8498de4139effecd1f33.tar.gz
Add the half of time-of-day clock resolution when we adjust system time from
time-of-day clock or vice versa. For x86 systems, RTC resolution is one second and we used to lose up to one second whenever we initialize system time from RTC or write system time back to RTC. With this change, margin of error per conversion is roughly between -0.5 and +0.5 second rather than between -1 and 0 second. Note that it does not take care of errors from getnanotime(9) (which is up to 1/hz second) or CLOCK_GETTIME() latency. These are just too expensive to correct and it is not worthy of the cost.
Diffstat (limited to 'sys/kern/subr_rtc.c')
-rw-r--r--sys/kern/subr_rtc.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/sys/kern/subr_rtc.c b/sys/kern/subr_rtc.c
index a38c8c9..120ad5f 100644
--- a/sys/kern/subr_rtc.c
+++ b/sys/kern/subr_rtc.c
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
static device_t clock_dev = NULL;
static long clock_res;
+static struct timespec clock_adj;
/* XXX: should be kern. now, it's no longer machdep. */
static int disable_rtc_set;
@@ -87,9 +88,12 @@ clock_register(device_t dev, long res) /* res has units of microseconds */
}
clock_dev = dev;
clock_res = res;
+ clock_adj.tv_sec = res / 2 / 1000000;
+ clock_adj.tv_nsec = res / 2 % 1000000 * 1000;
if (bootverbose)
device_printf(dev, "registered as a time-of-day clock "
- "(resolution %ldus)\n", res);
+ "(resolution %ldus, adjustment %jd.%09jds)\n", res,
+ (intmax_t)clock_adj.tv_sec, (intmax_t)clock_adj.tv_nsec);
}
/*
@@ -127,6 +131,7 @@ inittodr(time_t base)
}
ts.tv_sec += utc_offset();
+ timespecadd(&ts, &clock_adj);
tc_setclock(&ts);
return;
@@ -151,6 +156,7 @@ resettodr(void)
return;
getnanotime(&ts);
+ timespecadd(&ts, &clock_adj);
ts.tv_sec -= utc_offset();
/* XXX: We should really set all registered RTCs */
if ((error = CLOCK_SETTIME(clock_dev, &ts)) != 0)
OpenPOWER on IntegriCloud