summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_tc.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2003-08-16 08:23:53 +0000
committerphk <phk@FreeBSD.org>2003-08-16 08:23:53 +0000
commit34014d52616ca61b0b5cf0a932b010bfadd29dba (patch)
tree1ba852aeb06396d333d240e0c07a660ad77cea18 /sys/kern/kern_tc.c
parente40caa9ae772a64d31f35f65258dec9f48d8a539 (diff)
downloadFreeBSD-src-34014d52616ca61b0b5cf0a932b010bfadd29dba.zip
FreeBSD-src-34014d52616ca61b0b5cf0a932b010bfadd29dba.tar.gz
Give timecounters a numeric quality field.
A timecounter will be selected when registered if its quality is not negative and no less than the current timecounters. Add a sysctl to report all available timecounters and their qualities. Give the dummy timecounter a solid negative quality of minus a million. Give the i8254 zero and the ACPI 1000. The TSC gets 800, unless APM or SMP forces it negative. Other timecounters default to zero quality and thereby retain current selection behaviour.
Diffstat (limited to 'sys/kern/kern_tc.c')
-rw-r--r--sys/kern/kern_tc.c43
1 files changed, 35 insertions, 8 deletions
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 379a64a..a3cef31 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -43,7 +43,7 @@ dummy_get_timecount(struct timecounter *tc)
}
static struct timecounter dummy_timecounter = {
- dummy_get_timecount, 0, ~0u, 1000000, "dummy",
+ dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000
};
struct timehands {
@@ -281,29 +281,33 @@ getmicrotime(struct timeval *tvp)
}
/*
- * Initialize a new timecounter.
- * We should really try to rank the timecounters and intelligently determine
- * if the new timecounter is better than the current one. This is subject
- * to further study. For now always use the new timecounter.
+ * Initialize a new timecounter and possibly use it.
*/
void
tc_init(struct timecounter *tc)
{
unsigned u;
- printf("Timecounter \"%s\" frequency %ju Hz",
- tc->tc_name, (intmax_t)tc->tc_frequency);
+ if (tc->tc_quality >= 0 || bootverbose)
+ printf("Timecounter \"%s\" frequency %ju Hz quality %d",
+ tc->tc_name, (intmax_t)tc->tc_frequency,
+ tc->tc_quality);
u = tc->tc_frequency / tc->tc_counter_mask;
if (u > hz) {
printf(" -- Insufficient hz, needs at least %u\n", u);
return;
}
+ printf("\n");
tc->tc_next = timecounters;
timecounters = tc;
- printf("\n");
(void)tc->tc_get_timecount(tc);
(void)tc->tc_get_timecount(tc);
+ /* Never automatically use a timecounter with negative quality */
+ if (tc->tc_quality < 0)
+ return;
+ if (tc->tc_quality < timecounter->tc_quality)
+ return;
timecounter = tc;
}
@@ -496,6 +500,29 @@ sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS)
SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW,
0, 0, sysctl_kern_timecounter_hardware, "A", "");
+
+/* Report or change the active timecounter hardware. */
+static int
+sysctl_kern_timecounter_choice(SYSCTL_HANDLER_ARGS)
+{
+ char buf[32], *spc;
+ struct timecounter *tc;
+ int error;
+
+ spc = "";
+ error = 0;
+ for (tc = timecounters; error == 0 && tc != NULL; tc = tc->tc_next) {
+ sprintf(buf, "%s%s(%d)",
+ spc, tc->tc_name, tc->tc_quality);
+ error = SYSCTL_OUT(req, buf, strlen(buf));
+ spc = " ";
+ }
+ return (error);
+}
+
+SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD,
+ 0, 0, sysctl_kern_timecounter_choice, "A", "");
+
/*
* RFC 2783 PPS-API implementation.
*/
OpenPOWER on IntegriCloud