summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1999-07-18 15:07:20 +0000
committerbde <bde@FreeBSD.org>1999-07-18 15:07:20 +0000
commit9ea61245a8fa724c231c6740852b5a8bc59549ac (patch)
treebc31fd524267dd705b46a40fbc5a62ff6dc3603d
parenta686f581bc15ec73b10b8f70547c9f1ee0d10e5e (diff)
downloadFreeBSD-src-9ea61245a8fa724c231c6740852b5a8bc59549ac.zip
FreeBSD-src-9ea61245a8fa724c231c6740852b5a8bc59549ac.tar.gz
Added a sysctl "kern.timecounter.hardware" for selecting the hardware
used for timecounting. The possible values are the names of the physically present harware timecounters ("i8254" and "TSC" on i386's). Fixed some nearby bitrot in comments in <sys/time.h>. Reviewed by: phk
-rw-r--r--sys/kern/kern_clock.c47
-rw-r--r--sys/kern/kern_tc.c47
-rw-r--r--sys/sys/time.h12
-rw-r--r--sys/sys/timetc.h12
4 files changed, 98 insertions, 20 deletions
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index 23918b1..de15f18 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -37,7 +37,7 @@
* SUCH DAMAGE.
*
* @(#)kern_clock.c 8.5 (Berkeley) 1/21/94
- * $Id: kern_clock.c,v 1.94 1999/04/25 08:59:59 phk Exp $
+ * $Id: kern_clock.c,v 1.95 1999/07/18 01:35:26 jdp Exp $
*/
#include "opt_ntp.h"
@@ -679,7 +679,14 @@ init_timecounter(struct timecounter *tc)
tc->tc_tweak = tc;
tco_setscales(tc);
tc->tc_offset_count = tc->tc_get_timecount(tc);
+ if (timecounter == &dummy_timecounter)
+ tc->tc_avail = tc;
+ else {
+ tc->tc_avail = timecounter->tc_tweak->tc_avail;
+ timecounter->tc_tweak->tc_avail = tc;
+ }
MALLOC(t1, struct timecounter *, sizeof *t1, M_TIMECOUNTER, M_WAITOK);
+ tc->tc_other = t1;
*t1 = *tc;
t2 = t1;
for (i = 1; i < NTIMECOUNTER; i++) {
@@ -720,9 +727,7 @@ set_timecounter(struct timespec *ts)
tco_forward(1);
}
-
-#if 0 /* Currently unused */
-void
+static void
switch_timecounter(struct timecounter *newtc)
{
int s;
@@ -731,19 +736,20 @@ switch_timecounter(struct timecounter *newtc)
s = splclock();
tc = timecounter;
- if (newtc == tc || newtc == tc->tc_other) {
+ if (newtc->tc_tweak == tc->tc_tweak) {
splx(s);
return;
}
+ newtc = newtc->tc_tweak->tc_other;
nanouptime(&ts);
newtc->tc_offset_sec = ts.tv_sec;
newtc->tc_offset_nano = (u_int64_t)ts.tv_nsec << 32;
newtc->tc_offset_micro = ts.tv_nsec / 1000;
newtc->tc_offset_count = newtc->tc_get_timecount(newtc);
+ tco_setscales(newtc);
timecounter = newtc;
splx(s);
}
-#endif
static struct timecounter *
sync_other_counter(void)
@@ -825,6 +831,35 @@ SYSCTL_INT(_kern_timecounter, OID_AUTO, method, CTLFLAG_RW, &tco_method, 0,
);
+static int
+sysctl_kern_timecounter_hardware SYSCTL_HANDLER_ARGS
+{
+ char newname[32];
+ struct timecounter *newtc, *tc;
+ int error;
+
+ tc = timecounter->tc_tweak;
+ strncpy(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) {
+ for (newtc = tc->tc_avail; newtc != tc; newtc = tc->tc_avail) {
+ if (strcmp(newname, newtc->tc_name) == 0) {
+ /* Warm up new timecounter. */
+ (void)newtc->tc_get_timecount(newtc);
+
+ switch_timecounter(newtc);
+ return (0);
+ }
+ }
+ return (EINVAL);
+ }
+ return (error);
+}
+
+SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW,
+ 0, 0, sysctl_kern_timecounter_hardware, "A", "");
+
int
pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 23918b1..de15f18 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.94 1999/04/25 08:59:59 phk Exp $
+ * $Id: kern_clock.c,v 1.95 1999/07/18 01:35:26 jdp Exp $
*/
#include "opt_ntp.h"
@@ -679,7 +679,14 @@ init_timecounter(struct timecounter *tc)
tc->tc_tweak = tc;
tco_setscales(tc);
tc->tc_offset_count = tc->tc_get_timecount(tc);
+ if (timecounter == &dummy_timecounter)
+ tc->tc_avail = tc;
+ else {
+ tc->tc_avail = timecounter->tc_tweak->tc_avail;
+ timecounter->tc_tweak->tc_avail = tc;
+ }
MALLOC(t1, struct timecounter *, sizeof *t1, M_TIMECOUNTER, M_WAITOK);
+ tc->tc_other = t1;
*t1 = *tc;
t2 = t1;
for (i = 1; i < NTIMECOUNTER; i++) {
@@ -720,9 +727,7 @@ set_timecounter(struct timespec *ts)
tco_forward(1);
}
-
-#if 0 /* Currently unused */
-void
+static void
switch_timecounter(struct timecounter *newtc)
{
int s;
@@ -731,19 +736,20 @@ switch_timecounter(struct timecounter *newtc)
s = splclock();
tc = timecounter;
- if (newtc == tc || newtc == tc->tc_other) {
+ if (newtc->tc_tweak == tc->tc_tweak) {
splx(s);
return;
}
+ newtc = newtc->tc_tweak->tc_other;
nanouptime(&ts);
newtc->tc_offset_sec = ts.tv_sec;
newtc->tc_offset_nano = (u_int64_t)ts.tv_nsec << 32;
newtc->tc_offset_micro = ts.tv_nsec / 1000;
newtc->tc_offset_count = newtc->tc_get_timecount(newtc);
+ tco_setscales(newtc);
timecounter = newtc;
splx(s);
}
-#endif
static struct timecounter *
sync_other_counter(void)
@@ -825,6 +831,35 @@ SYSCTL_INT(_kern_timecounter, OID_AUTO, method, CTLFLAG_RW, &tco_method, 0,
);
+static int
+sysctl_kern_timecounter_hardware SYSCTL_HANDLER_ARGS
+{
+ char newname[32];
+ struct timecounter *newtc, *tc;
+ int error;
+
+ tc = timecounter->tc_tweak;
+ strncpy(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) {
+ for (newtc = tc->tc_avail; newtc != tc; newtc = tc->tc_avail) {
+ if (strcmp(newname, newtc->tc_name) == 0) {
+ /* Warm up new timecounter. */
+ (void)newtc->tc_get_timecount(newtc);
+
+ switch_timecounter(newtc);
+ return (0);
+ }
+ }
+ return (EINVAL);
+ }
+ return (error);
+}
+
+SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW,
+ 0, 0, sysctl_kern_timecounter_hardware, "A", "");
+
int
pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
diff --git a/sys/sys/time.h b/sys/sys/time.h
index 43821b6..32ea4a0 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)time.h 8.5 (Berkeley) 5/4/95
- * $Id: time.h,v 1.37 1999/03/11 15:09:41 phk Exp $
+ * $Id: time.h,v 1.38 1999/04/25 08:59:55 phk Exp $
*/
#ifndef _SYS_TIME_H_
@@ -121,11 +121,14 @@ struct timezone {
* used in a safe way. Such changes may be adopted with a delay of up to 1/HZ,
* index one & two are used alternately for the actual timekeeping.
*
- * `other' points to the opposite "work" timecounter, ie, in index one it
- * points to index two and vice versa
+ * 'tc_avail' points to the next available (external) timecounter in a
+ * circular queue. This is only valid for index 0.
*
- * `tweak' points to index zero.
+ * `tc_other' points to the next "work" timecounter in a circular queue,
+ * i.e., for index i > 0 it points to index 1 + (i - 1) % NTIMECOUNTER.
+ * We also use it to point from index 0 to index 1.
*
+ * `tc_tweak' points to index 0.
*/
struct timecounter;
@@ -151,6 +154,7 @@ struct timecounter {
u_int64_t tc_offset_nano;
struct timeval tc_microtime;
struct timespec tc_nanotime;
+ struct timecounter *tc_avail;
struct timecounter *tc_other;
struct timecounter *tc_tweak;
};
diff --git a/sys/sys/timetc.h b/sys/sys/timetc.h
index 43821b6..32ea4a0 100644
--- a/sys/sys/timetc.h
+++ b/sys/sys/timetc.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)time.h 8.5 (Berkeley) 5/4/95
- * $Id: time.h,v 1.37 1999/03/11 15:09:41 phk Exp $
+ * $Id: time.h,v 1.38 1999/04/25 08:59:55 phk Exp $
*/
#ifndef _SYS_TIME_H_
@@ -121,11 +121,14 @@ struct timezone {
* used in a safe way. Such changes may be adopted with a delay of up to 1/HZ,
* index one & two are used alternately for the actual timekeeping.
*
- * `other' points to the opposite "work" timecounter, ie, in index one it
- * points to index two and vice versa
+ * 'tc_avail' points to the next available (external) timecounter in a
+ * circular queue. This is only valid for index 0.
*
- * `tweak' points to index zero.
+ * `tc_other' points to the next "work" timecounter in a circular queue,
+ * i.e., for index i > 0 it points to index 1 + (i - 1) % NTIMECOUNTER.
+ * We also use it to point from index 0 to index 1.
*
+ * `tc_tweak' points to index 0.
*/
struct timecounter;
@@ -151,6 +154,7 @@ struct timecounter {
u_int64_t tc_offset_nano;
struct timeval tc_microtime;
struct timespec tc_nanotime;
+ struct timecounter *tc_avail;
struct timecounter *tc_other;
struct timecounter *tc_tweak;
};
OpenPOWER on IntegriCloud