summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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