diff options
-rw-r--r-- | sys/kern/kern_clock.c | 23 | ||||
-rw-r--r-- | sys/kern/kern_time.c | 35 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 4 | ||||
-rw-r--r-- | sys/sys/time.h | 3 |
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 *); |