diff options
-rw-r--r-- | share/man/man4/timecounters.4 | 14 | ||||
-rw-r--r-- | sys/kern/kern_tc.c | 18 |
2 files changed, 23 insertions, 9 deletions
diff --git a/share/man/man4/timecounters.4 b/share/man/man4/timecounters.4 index 9abb522..52c68d7 100644 --- a/share/man/man4/timecounters.4 +++ b/share/man/man4/timecounters.4 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 12, 2014 +.Dd August 12, 2015 .Dt TIMECOUNTERS 4 .Os .Sh NAME @@ -96,10 +96,16 @@ compared to others. A negative value means this time counter is broken and should not be used. .El .Pp -The time management code of the kernel chooses one time counter from that list. -The current choice can be read and affected via the +The time management code of the kernel automatically switches to a +higher-quality time counter when it registers, unless the .Va kern.timecounter.hardware -tunable/sysctl. +sysctl has been used to choose a specific device. +.Pp +There is no way to unregister a time counter once it has registered +with the kernel. +If a dynamically loaded module contains a time counter you will not +be able to unload that module, even if the time counter it contains +is not the one currently in use. .Sh SEE ALSO .Xr attimer 4 , .Xr eventtimers 4 , diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index d09f0b6..432e38a 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -133,6 +133,8 @@ SYSCTL_PROC(_kern_timecounter, OID_AUTO, alloweddeviation, sysctl_kern_timecounter_adjprecision, "I", "Allowed time interval deviation in percents"); +static int tc_chosen; /* Non-zero if a specific tc was chosen via sysctl. */ + static void tc_windup(void); static void cpu_tick_calibrate(int); @@ -1197,10 +1199,13 @@ tc_init(struct timecounter *tc) "quality", CTLFLAG_RD, &(tc->tc_quality), 0, "goodness of time counter"); /* - * Never automatically use a timecounter with negative quality. + * Do not automatically switch if the current tc was specifically + * chosen. Never automatically use a timecounter with negative quality. * Even though we run on the dummy counter, switching here may be - * worse since this timecounter may not be monotonous. + * worse since this timecounter may not be monotonic. */ + if (tc_chosen) + return; if (tc->tc_quality < 0) return; if (tc->tc_quality < timecounter->tc_quality) @@ -1433,9 +1438,12 @@ sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS) strlcpy(newname, tc->tc_name, sizeof(newname)); error = sysctl_handle_string(oidp, &newname[0], sizeof(newname), req); - if (error != 0 || req->newptr == NULL || - strcmp(newname, tc->tc_name) == 0) + if (error != 0 || req->newptr == NULL) return (error); + /* Record that the tc in use now was specifically chosen. */ + tc_chosen = 1; + if (strcmp(newname, tc->tc_name) == 0) + return (0); for (newtc = timecounters; newtc != NULL; newtc = newtc->tc_next) { if (strcmp(newname, newtc->tc_name) != 0) continue; @@ -1464,7 +1472,7 @@ SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW, "Timecounter hardware selected"); -/* Report or change the active timecounter hardware. */ +/* Report the available timecounter hardware. */ static int sysctl_kern_timecounter_choice(SYSCTL_HANDLER_ARGS) { |