diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_ntptime.c | 74 | ||||
-rw-r--r-- | sys/kern/kern_tc.c | 23 | ||||
-rw-r--r-- | sys/kern/kern_time.c | 72 | ||||
-rw-r--r-- | sys/kern/subr_param.c | 2 | ||||
-rw-r--r-- | sys/sys/kernel.h | 3 |
5 files changed, 78 insertions, 96 deletions
diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c index 4a9c7a6..d8218db 100644 --- a/sys/kern/kern_ntptime.c +++ b/sys/kern/kern_ntptime.c @@ -152,6 +152,8 @@ static l_fp time_offset; /* time offset (ns) */ static l_fp time_freq; /* frequency offset (ns/s) */ static l_fp time_adj; /* tick adjust (ns/s) */ +static int64_t time_adjtime; /* correction from adjtime(2) (usec) */ + #ifdef PPS_SYNC /* * The following variables are used when a pulse-per-second (PPS) signal @@ -437,6 +439,7 @@ void ntp_update_second(struct timecounter *tcp) { u_int32_t *newsec; + int tickrate; l_fp ftemp; /* 32/64-bit temporary */ newsec = &tcp->tc_offset.sec; @@ -532,7 +535,31 @@ ntp_update_second(struct timecounter *tcp) time_adj = ftemp; L_SUB(time_offset, ftemp); L_ADD(time_adj, time_freq); + + /* + * Apply any correction from adjtime(2). If more than one second + * off we slew at a rate of 5ms/s (5000 PPM) else 500us/s (500PPM) + * until the last second is slewed the final < 500 usecs. + */ + if (time_adjtime != 0) { + if (time_adjtime > 1000000) + tickrate = 5000; + else if (time_adjtime < -1000000) + tickrate = -5000; + else if (time_adjtime > 500) + tickrate = 500; + else if (time_adjtime < -500) + tickrate = -500; + else if (time_adjtime != 0) + tickrate = time_adjtime; + else + tickrate = 0; /* GCC sucks! */ + time_adjtime -= tickrate; + L_LINT(ftemp, tickrate * 1000); + L_ADD(time_adj, ftemp); + } tcp->tc_adjustment = time_adj; + #ifdef PPS_SYNC if (pps_valid > 0) pps_valid--; @@ -865,3 +892,50 @@ hardpps(tsp, nsec) time_freq = pps_freq; } #endif /* PPS_SYNC */ + +#ifndef _SYS_SYSPROTO_H_ +struct adjtime_args { + struct timeval *delta; + struct timeval *olddelta; +}; +#endif +/* + * MPSAFE + */ +/* ARGSUSED */ +int +adjtime(struct thread *td, struct adjtime_args *uap) +{ + struct timeval atv; + int error; + + mtx_lock(&Giant); + + if ((error = suser(td))) + goto done2; + if (uap->olddelta) { + atv.tv_sec = time_adjtime / 1000000; + atv.tv_usec = time_adjtime % 1000000; + if (atv.tv_usec < 0) { + atv.tv_usec += 1000000; + atv.tv_sec--; + } + printf("Old: time_adjtime = %ld.%06ld %lld\n", + atv.tv_sec, atv.tv_usec, time_adjtime); + error = copyout(&atv, uap->olddelta, sizeof(atv)); + if (error) + goto done2; + } + if (uap->delta) { + error = copyin(uap->delta, &atv, sizeof(atv)); + if (error) + goto done2; + time_adjtime = (int64_t)atv.tv_sec * 1000000 + atv.tv_usec; + printf("New: time_adjtime = %ld.%06ld %lld\n", + atv.tv_sec, atv.tv_usec, time_adjtime); + } +done2: + mtx_unlock(&Giant); + return (error); +} + diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index e058e74..18e3ce3 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -238,11 +238,11 @@ tco_setscales(struct timecounter *tc) /* * We get nanoseconds with 32 bit binary fraction and want * 64 bit binary fraction: x = a * 2^32 / 10^9 = a * 4.294967296 - * The range is +/- 500PPM so we can only multiply by about 8500 - * without overflowing. The best suitable fraction is 4398/1024. - * Divide by 2 times 1024 to match the temporary lower precision. + * The range is +/- 5000PPM so we can only multiply by about 850 + * without overflowing. The best suitable fraction is 2199/512. + * Divide by 2 times 512 to match the temporary lower precision. */ - scale += (tc->tc_adjustment * 4398) / 2048; + scale += (tc->tc_adjustment / 1024) * 2199; scale /= tc->tc_tweak->tc_frequency; tc->tc_scale = scale * 2; } @@ -338,7 +338,6 @@ tc_windup(void) { struct timecounter *tc, *tco; struct bintime bt; - struct timeval tvt; unsigned ogen, delta; int i; @@ -362,20 +361,6 @@ tc_windup(void) */ if (tco->tc_poll_pps) tco->tc_poll_pps(tco); - if (timedelta != 0) { - tvt = boottime; - tvt.tv_usec += tickdelta; - if (tvt.tv_usec >= 1000000) { - tvt.tv_sec++; - tvt.tv_usec -= 1000000; - } else if (tvt.tv_usec < 0) { - tvt.tv_sec--; - tvt.tv_usec += 1000000; - } - boottime = tvt; - timeval2bintime(&boottime, &boottimebin); - timedelta -= tickdelta; - } for (i = tc->tc_offset.sec - tco->tc_offset.sec; i > 0; i--) { ntp_update_second(tc); /* XXX only needed if xntpd runs */ tco_setscales(tc); 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 diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c index 8c2e4c6..820fe0107 100644 --- a/sys/kern/subr_param.c +++ b/sys/kern/subr_param.c @@ -65,7 +65,6 @@ int hz; int tick; -int tickadj; /* can adjust 30ms in 60s */ int maxusers; /* base tunable */ int maxproc; /* maximum # of processes */ int maxprocperuid; /* max # of procs per user */ @@ -100,7 +99,6 @@ init_param1(void) hz = HZ; TUNABLE_INT_FETCH("kern.hz", &hz); tick = 1000000 / hz; - tickadj = howmany(30000, 60 * hz); /* can adjust 30ms in 60s */ #ifdef VM_SWZONE_SIZE_MAX maxswzone = VM_SWZONE_SIZE_MAX; diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index 7bc3a3e..9eff1b6 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -71,15 +71,12 @@ extern struct timeval boottime; extern struct timezone tz; /* XXX */ extern int tick; /* usec per tick (1000000 / hz) */ -extern int tickadj; /* "standard" clock skew, us./tick */ extern int hz; /* system clock's frequency */ extern int psratio; /* ratio: prof / stat */ extern int stathz; /* statistics clock's frequency */ extern int profhz; /* profiling clock's frequency */ extern int ticks; extern int lbolt; /* once a second sleep address */ -extern int tickdelta; -extern long timedelta; #endif /* _KERNEL */ |