From 04257819a4d326980d051f445ae317d8cd16374b Mon Sep 17 00:00:00 2001 From: phk Date: Fri, 26 Apr 2002 12:37:36 +0000 Subject: Move the winding of timecounters out of hardclock and into a normal timeout loop. Limit the rate at which we wind the timecounters to approx 1000 Hz. This limits the precision of the get{bin,nano,micro}[up]time(9) functions to roughly a millisecond. --- sys/kern/kern_clock.c | 3 --- sys/kern/kern_tc.c | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 4 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index e613eb6..92175b8 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -53,8 +53,6 @@ #include #include #include -#include -#include #include #include #include @@ -218,7 +216,6 @@ hardclock(frame) if (stathz == 0) statclock(frame); - tc_windup(); #ifdef DEVICE_POLLING hardclock_device_poll(); /* this is very short and quick */ #endif /* DEVICE_POLLING */ diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index d403847..aee3eaa 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -50,6 +50,8 @@ TC_STATS(ngetbintime); TC_STATS(ngetnanotime); TC_STATS(ngetmicrotime); #undef TC_STATS +static void tc_windup(void); + /* * Implement a dummy timecounter which we can use until we get a real one * in the air. This allows the console and other early stuff to use @@ -332,7 +334,7 @@ switch_timecounter(struct timecounter *newtc) splx(s); } -void +static void tc_windup(void) { struct timecounter *tc, *tco; @@ -547,3 +549,39 @@ pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int eve } #endif } + +/*- + * Timecounters need to be updated every so often to prevent the hardware + * counter from overflowing. Updating also recalculates the cached values + * used by the get*() family of functions, so their precision depends on + * the update frequency. + * Don't update faster than approx once per millisecond, if people want + * better timestamps they should use the non-"get" functions. + */ + +static int tc_tick; +SYSCTL_INT(_kern_timecounter, OID_AUTO, tick, CTLFLAG_RD, &tick, 0, ""); + +static void +tc_ticktock(void *dummy) +{ + + tc_windup(); + timeout(tc_ticktock, NULL, tc_tick); +} + +static void +inittimecounter(void *dummy) +{ + u_int p; + + if (hz > 1000) + tc_tick = (hz + 500) / 1000; + else + tc_tick = 1; + p = (tc_tick * 1000000) / hz; + printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000); + tc_ticktock(NULL); +} + +SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_FIRST, inittimecounter, NULL) -- cgit v1.1