diff options
Diffstat (limited to 'sys/kern/kern_tc.c')
-rw-r--r-- | sys/kern/kern_tc.c | 43 |
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. */ |