diff options
author | phk <phk@FreeBSD.org> | 1998-11-29 20:31:02 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 1998-11-29 20:31:02 +0000 |
commit | b493bd5ba3fb70332d87e0966e2419fcbdc4afa0 (patch) | |
tree | bb2498905ffb323a4a962f2e4553585a65618db2 /sys/kern/kern_tc.c | |
parent | 0c339fec9efb498da17fe5dd4a1a2525faf6340b (diff) | |
download | FreeBSD-src-b493bd5ba3fb70332d87e0966e2419fcbdc4afa0.zip FreeBSD-src-b493bd5ba3fb70332d87e0966e2419fcbdc4afa0.tar.gz |
Make the previous behaviour the default, add a sysctl which you
can set if your hw/sw produces the "calcru negative..." message.
Setting the alternate method (sysctl -w kern.timecounter.method=1)
makes the the get{nano|micro}*() functions call the real thing at
resulting in a measurable but minor overhead.
I decided to NOT have the "calcru" change the method automatically
because you should be aware of this problem if you have it.
The problems currently seen, related to usleep and a few other corners
are fixed for both methods.
Diffstat (limited to 'sys/kern/kern_tc.c')
-rw-r--r-- | sys/kern/kern_tc.c | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index 22005c2..2ea378f 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * @(#)kern_clock.c 8.5 (Berkeley) 1/21/94 - * $Id: kern_clock.c,v 1.84 1998/11/23 09:34:19 sos Exp $ + * $Id: kern_clock.c,v 1.85 1998/11/23 09:58:53 phk Exp $ */ #include <sys/param.h> @@ -102,6 +102,13 @@ long tk_rawcc; time_t time_second; /* + * Which update policy to use. + * 0 - every tick, bad hardware may fail with "calcru negative..." + * 1 - more resistent to the above hardware, but less efficient. + */ +static int tco_method; + +/* * 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 * timeservices. @@ -515,8 +522,12 @@ getmicrotime(struct timeval *tvp) { struct timecounter *tc; - tc = timecounter; - *tvp = tc->tc_microtime; + if (!tco_method) { + tc = timecounter; + *tvp = tc->tc_microtime; + } else { + microtime(tvp); + } } void @@ -524,8 +535,12 @@ getnanotime(struct timespec *tsp) { struct timecounter *tc; - tc = timecounter; - *tsp = tc->tc_nanotime; + if (!tco_method) { + tc = timecounter; + *tsp = tc->tc_nanotime; + } else { + nanotime(tsp); + } } void @@ -596,9 +611,13 @@ getmicrouptime(struct timeval *tvp) { struct timecounter *tc; - tc = timecounter; - tvp->tv_sec = tc->tc_offset_sec; - tvp->tv_usec = tc->tc_offset_micro; + if (!tco_method) { + tc = timecounter; + tvp->tv_sec = tc->tc_offset_sec; + tvp->tv_usec = tc->tc_offset_micro; + } else { + microuptime(tvp); + } } void @@ -606,9 +625,13 @@ getnanouptime(struct timespec *tsp) { struct timecounter *tc; - tc = timecounter; - tsp->tv_sec = tc->tc_offset_sec; - tsp->tv_nsec = tc->tc_offset_nano >> 32; + if (!tco_method) { + tc = timecounter; + tsp->tv_sec = tc->tc_offset_sec; + tsp->tv_nsec = tc->tc_offset_nano >> 32; + } else { + nanouptime(tsp); + } } void @@ -793,7 +816,7 @@ tco_forward(int force) force++; } - if (!force) + if (tco_method && !force) return; tc->tc_offset_micro = (tc->tc_offset_nano / 1000) >> 32; @@ -833,6 +856,13 @@ sysctl_kern_timecounter_adjustment SYSCTL_HANDLER_ARGS SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, ""); +SYSCTL_INT(_kern_timecounter, KERN_ARGMAX, method, CTLFLAG_RW, &tco_method, 0, + "This variable determines the method used for updating timecounters. " + "If the default algorithm (0) fails with \"calcru negative...\" messages " + "try the alternate algorithm (1) which handles bad hardware better." + +); + SYSCTL_PROC(_kern_timecounter, OID_AUTO, frequency, CTLTYPE_INT | CTLFLAG_RW, 0, sizeof(u_int), sysctl_kern_timecounter_frequency, "I", ""); |