summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_clock.c23
-rw-r--r--sys/kern/kern_time.c35
-rw-r--r--sys/kern/syscalls.master4
-rw-r--r--sys/sys/time.h3
4 files changed, 61 insertions, 4 deletions
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index 482b349be91..30140b0688d 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_clock.c,v 1.58 2006/01/20 07:53:48 tedu Exp $ */
+/* $OpenBSD: kern_clock.c,v 1.59 2006/06/14 19:52:07 otto Exp $ */
/* $NetBSD: kern_clock.c,v 1.34 1996/06/09 04:51:03 briggs Exp $ */
/*-
@@ -222,6 +222,8 @@ hardclock(struct clockframe *frame)
int delta;
extern int tickdelta;
extern long timedelta;
+ extern int64_t ntp_tick_permanent;
+ extern int64_t ntp_tick_acc;
#endif
#ifdef __HAVE_CPUINFO
struct cpu_info *ci = curcpu();
@@ -287,6 +289,25 @@ hardclock(struct clockframe *frame)
timedelta -= tickdelta;
}
+ /*
+ * ntp_tick_permanent accumulates the clock correction each
+ * tick. The unit is ns per tick shifted left 32 bits. If we have
+ * accumulated more than 1us, we bump delta in the right
+ * direction. Use a loop to avoid long long div; typicallly
+ * the loops will be executed 0 or 1 iteration.
+ */
+ if (ntp_tick_permanent != 0) {
+ ntp_tick_acc += ntp_tick_permanent;
+ while (ntp_tick_acc >= (1000LL << 32)) {
+ delta++;
+ ntp_tick_acc -= (1000LL << 32);
+ }
+ while (ntp_tick_acc <= -(1000LL << 32)) {
+ delta--;
+ ntp_tick_acc += (1000LL << 32);
+ }
+ }
+
BUMPTIME(&time, delta);
BUMPTIME(&mono_time, delta);
time_second = time.tv_sec;
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 7bffe722027..efe209890c9 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_time.c,v 1.55 2006/06/04 18:47:33 otto Exp $ */
+/* $OpenBSD: kern_time.c,v 1.56 2006/06/14 19:52:07 otto Exp $ */
/* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */
/*
@@ -354,10 +354,42 @@ struct timeval adjtimedelta; /* unapplied time correction */
int tickdelta; /* current clock skew, us. per tick */
long timedelta; /* unapplied time correction, us. */
long bigadj = 1000000; /* use 10x skew above bigadj us. */
+int64_t ntp_tick_permanent;
+int64_t ntp_tick_acc;
#endif
/* ARGSUSED */
int
+sys_adjfreq(struct proc *p, void *v, register_t *retval)
+{
+ struct sys_adjfreq_args /* {
+ syscallarg(const int64_t *) freq;
+ syscallarg(int64_t *) oldfreq;
+ } */ *uap = v;
+ int error, s;
+ int64_t f;
+
+ if (SCARG(uap, oldfreq)) {
+ f = ntp_tick_permanent * hz;
+ if ((error = copyout((void *)&f, (void *)SCARG(uap, oldfreq),
+ sizeof(int64_t))))
+ return (error);
+ }
+ if (SCARG(uap, freq)) {
+ if ((error = suser(p, 0)))
+ return (error);
+ if ((error = copyin((void *)SCARG(uap, freq), (void *)&f,
+ sizeof(int64_t))))
+ return (error);
+ s = splclock();
+ ntp_tick_permanent = f / hz;
+ splx(s);
+ }
+ return (0);
+}
+
+/* ARGSUSED */
+int
sys_adjtime(struct proc *p, void *v, register_t *retval)
{
struct sys_adjtime_args /* {
@@ -450,6 +482,7 @@ out:
#endif
}
+
/*
* Get value of an interval timer. The process virtual and
* profiling virtual time timers are kept in the p_stats area, since
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 435821b53a4..016743e431f 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -1,4 +1,4 @@
-; $OpenBSD: syscalls.master,v 1.83 2006/06/09 00:05:54 deraadt Exp $
+; $OpenBSD: syscalls.master,v 1.84 2006/06/14 19:52:07 otto Exp $
; $NetBSD: syscalls.master,v 1.32 1996/04/23 10:24:21 mycroft Exp $
; @(#)syscalls.master 8.2 (Berkeley) 1/13/94
@@ -609,3 +609,5 @@
303 UNIMPL
#endif
304 STD { int sys___getcwd(char *buf, size_t len); }
+305 STD { int sys_adjfreq(const int64_t *freq, \
+ int64_t *oldfreq); }
diff --git a/sys/sys/time.h b/sys/sys/time.h
index 5125db547f3..4d905532e37 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: time.h,v 1.21 2005/12/13 00:35:23 millert Exp $ */
+/* $OpenBSD: time.h,v 1.22 2006/06/14 19:52:07 otto Exp $ */
/* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */
/*
@@ -318,6 +318,7 @@ int ppsratecheck(struct timeval *, int *, int);
__BEGIN_DECLS
#if __BSD_VISIBLE
int adjtime(const struct timeval *, struct timeval *);
+int adjfreq(const int64_t *, int64_t *);
#endif
#if __XPG_VISIBLE
int clock_getres(clockid_t, struct timespec *);