summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2014-01-30 21:02:00 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2014-01-30 21:02:00 +0000
commite161f073d9835d140e4f863d20a63ab15cfd9092 (patch)
treeebe8bc731574b977dfe3a3c6fbcfb3d69fc6bbb8 /sys
parent02c86de9dd6a2ec2439cef966e81dce0d33fb73f (diff)
Simplyfy adjtime(2) by keeping track of the adjustment as a number of
microsecond in a 64-bit integer. Fixes the issue where ntpd loses sync because the struct timeval currently used to hold the adjustment is not properly normalized after the changes guenther@ made. ok guenther@, millert@
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_tc.c21
-rw-r--r--sys/kern/kern_time.c41
-rw-r--r--sys/sys/kernel.h6
3 files changed, 30 insertions, 38 deletions
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 241aaa9e080..4d112aa4966 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
- * $OpenBSD: kern_tc.c,v 1.21 2013/10/06 01:27:49 guenther Exp $
+ * $OpenBSD: kern_tc.c,v 1.22 2014/01/30 21:01:59 kettenis Exp $
* $FreeBSD: src/sys/kern/kern_tc.c,v 1.148 2003/03/18 08:45:23 phk Exp $
*/
@@ -611,20 +611,15 @@ sysctl_tc(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void
ntp_update_second(int64_t *adjust, time_t *sec)
{
- struct timeval adj;
+ int64_t adj;
/* Skew time according to any adjtime(2) adjustments. */
- timerclear(&adj);
- if (adjtimedelta.tv_sec > 0)
- adj.tv_usec = 5000;
- else if (adjtimedelta.tv_sec == 0)
- adj.tv_usec = MIN(5000, adjtimedelta.tv_usec);
- else if (adjtimedelta.tv_sec < -1)
- adj.tv_usec = -5000;
- else if (adjtimedelta.tv_sec == -1)
- adj.tv_usec = MAX(-5000, adjtimedelta.tv_usec - 1000000);
- timersub(&adjtimedelta, &adj, &adjtimedelta);
- *adjust = ((int64_t)adj.tv_usec * 1000) << 32;
+ if (adjtimedelta > 0)
+ adj = MIN(5000, adjtimedelta);
+ else
+ adj = MAX(-5000, adjtimedelta);
+ adjtimedelta -= adj;
+ *adjust = (adj * 1000) << 32;
*adjust += timecounter->tc_freq_adj;
}
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 858d860b50f..f48c3a2af86 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_time.c,v 1.86 2014/01/22 00:48:36 guenther Exp $ */
+/* $OpenBSD: kern_time.c,v 1.87 2014/01/30 21:01:59 kettenis Exp $ */
/* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */
/*
@@ -46,7 +46,7 @@
#include <sys/syscallargs.h>
-struct timeval adjtimedelta; /* unapplied time correction */
+int64_t adjtimedelta; /* unapplied time correction (microseconds) */
/*
* Time of day and interval timer support.
@@ -68,8 +68,7 @@ settime(struct timespec *ts)
* Adjtime in progress is meaningless or harmful after
* setting the clock. Cancel adjtime and then set new time.
*/
- adjtimedelta.tv_usec = 0;
- adjtimedelta.tv_sec = 0;
+ adjtimedelta = 0;
/*
* Don't allow the time to be set forward so far it will wrap
@@ -428,37 +427,35 @@ sys_adjtime(struct proc *p, void *v, register_t *retval)
syscallarg(const struct timeval *) delta;
syscallarg(struct timeval *) olddelta;
} */ *uap = v;
- struct timeval newdelta;
const struct timeval *delta = SCARG(uap, delta);
struct timeval *olddelta = SCARG(uap, olddelta);
+ struct timeval atv;
int error;
- if (olddelta)
- if ((error = copyout(&adjtimedelta, olddelta,
- sizeof(struct timeval))))
+ if (olddelta) {
+ memset(&atv, 0, sizeof(atv));
+ atv.tv_sec = adjtimedelta / 1000000;
+ atv.tv_usec = adjtimedelta % 1000000;
+ if (atv.tv_usec < 0) {
+ atv.tv_usec += 1000000;
+ atv.tv_sec--;
+ }
+
+ if ((error = copyout(&atv, olddelta, sizeof(struct timeval))))
return (error);
+ }
if (delta) {
if ((error = suser(p, 0)))
return (error);
- if ((error = copyin(delta, &newdelta,
- sizeof(struct timeval))))
+ if ((error = copyin(delta, &atv, sizeof(struct timeval))))
return (error);
- /* Normalize the correction. */
- while (newdelta.tv_usec >= 1000000) {
- newdelta.tv_usec -= 1000000;
- newdelta.tv_sec += 1;
- }
- while (newdelta.tv_usec < 0) {
- newdelta.tv_usec += 1000000;
- newdelta.tv_sec -= 1;
- }
-
- adjtimedelta.tv_sec = newdelta.tv_sec;
- adjtimedelta.tv_usec = newdelta.tv_usec;
+ /* XXX Check for overflow? */
+ adjtimedelta = (int64_t)atv.tv_sec * 1000000 + atv.tv_usec;
}
+
return (0);
}
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
index 2668266c02c..292c4f82b39 100644
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kernel.h,v 1.15 2013/10/06 01:27:49 guenther Exp $ */
+/* $OpenBSD: kernel.h,v 1.16 2014/01/30 21:01:59 kettenis Exp $ */
/* $NetBSD: kernel.h,v 1.11 1995/03/03 01:24:16 cgd Exp $ */
/*-
@@ -61,5 +61,5 @@ extern int lbolt; /* once a second sleep address */
extern int tickdelta;
extern long timedelta;
-extern struct timeval adjtimedelta; /* unapplied time correction */
-extern struct bintime naptime; /* time spent suspended */
+extern int64_t adjtimedelta; /* unapplied time correction */
+extern struct bintime naptime; /* time spent suspended */