summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/timecounters.414
-rw-r--r--sys/kern/kern_tc.c18
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)
{
OpenPOWER on IntegriCloud