summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-04-26 12:37:36 +0000
committerphk <phk@FreeBSD.org>2002-04-26 12:37:36 +0000
commit04257819a4d326980d051f445ae317d8cd16374b (patch)
tree4e6b9f61f280b54de6b94c7eece10edcfaea8477 /sys/kern
parentc9e55ed3c8a1963b73b29b8b053a687385d658f6 (diff)
downloadFreeBSD-src-04257819a4d326980d051f445ae317d8cd16374b.zip
FreeBSD-src-04257819a4d326980d051f445ae317d8cd16374b.tar.gz
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.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_clock.c3
-rw-r--r--sys/kern/kern_tc.c40
2 files changed, 39 insertions, 4 deletions
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 <sys/resourcevar.h>
#include <sys/signalvar.h>
#include <sys/smp.h>
-#include <sys/timetc.h>
-#include <sys/timepps.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
@@ -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)
OpenPOWER on IntegriCloud