diff options
author | phk <phk@FreeBSD.org> | 2002-04-15 12:23:11 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2002-04-15 12:23:11 +0000 |
commit | b6bf4c07cfa2b20a71ec5c6e20bf929d299043c5 (patch) | |
tree | 733a8aba038268bb9bbfe0becf82c0d69fb2477b /sys/kern/kern_time.c | |
parent | 3bc1e338fc199c90b88b05b395b5a427f9497a15 (diff) | |
download | FreeBSD-src-b6bf4c07cfa2b20a71ec5c6e20bf929d299043c5.zip FreeBSD-src-b6bf4c07cfa2b20a71ec5c6e20bf929d299043c5.tar.gz |
Improve the implementation of adjtime(2).
Apply the change as a continuous slew rather than as a series of
discrete steps and make it possible to adjust arbitraryly huge
amounts of time in either direction.
In practice this is done by hooking into the same once-per-second
loop as the NTP PLL and setting a suitable frequency offset deducting
the amount slewed from the remainder. If the remaining delta is
larger than 1 second we slew at 5000PPM (5msec/sec), for a delta
less than a second we slew at 500PPM (500usec/sec) and for the last
one second period we will slew at whatever rate (less than 500PPM)
it takes to eliminate the delta entirely.
The old implementation stepped the clock a number of microseconds
every HZ to acheive the same effect, using the same rates of change.
Eliminate the global variables tickadj, tickdelta and timedelta and
their various use and initializations.
This removes the most significant obstacle to running timecounter and
NTP housekeeping from a timeout rather than hardclock.
Diffstat (limited to 'sys/kern/kern_time.c')
-rw-r--r-- | sys/kern/kern_time.c | 72 |
1 files changed, 0 insertions, 72 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index c24e9b0..fd86212 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -386,78 +386,6 @@ settimeofday(td, uap) } return (error); } - -int tickdelta; /* current clock skew, us. per tick */ -long timedelta; /* unapplied time correction, us. */ -static long bigadj = 1000000; /* use 10x skew above bigadj us. */ - -#ifndef _SYS_SYSPROTO_H_ -struct adjtime_args { - struct timeval *delta; - struct timeval *olddelta; -}; -#endif -/* - * MPSAFE - */ -/* ARGSUSED */ -int -adjtime(td, uap) - struct thread *td; - register struct adjtime_args *uap; -{ - struct timeval atv; - register long ndelta, ntickdelta, odelta; - int s, error; - - mtx_lock(&Giant); - - if ((error = suser(td))) - goto done2; - error = copyin((caddr_t)uap->delta, (caddr_t)&atv, - sizeof(struct timeval)); - if (error) - goto done2; - - /* - * Compute the total correction and the rate at which to apply it. - * Round the adjustment down to a whole multiple of the per-tick - * delta, so that after some number of incremental changes in - * hardclock(), tickdelta will become zero, lest the correction - * overshoot and start taking us away from the desired final time. - */ - ndelta = atv.tv_sec * 1000000 + atv.tv_usec; - if (ndelta > bigadj || ndelta < -bigadj) - ntickdelta = 10 * tickadj; - else - ntickdelta = tickadj; - if (ndelta % ntickdelta) - ndelta = ndelta / ntickdelta * ntickdelta; - - /* - * To make hardclock()'s job easier, make the per-tick delta negative - * if we want time to run slower; then hardclock can simply compute - * tick + tickdelta, and subtract tickdelta from timedelta. - */ - if (ndelta < 0) - ntickdelta = -ntickdelta; - s = splclock(); - odelta = timedelta; - timedelta = ndelta; - tickdelta = ntickdelta; - splx(s); - - if (uap->olddelta) { - atv.tv_sec = odelta / 1000000; - atv.tv_usec = odelta % 1000000; - (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta, - sizeof(struct timeval)); - } -done2: - mtx_unlock(&Giant); - return (error); -} - /* * Get value of an interval timer. The process virtual and * profiling virtual time timers are kept in the p_stats area, since |