diff options
-rw-r--r-- | sys/kern/kern_clock.c | 47 | ||||
-rw-r--r-- | sys/kern/kern_tc.c | 47 | ||||
-rw-r--r-- | sys/sys/time.h | 12 | ||||
-rw-r--r-- | sys/sys/timetc.h | 12 |
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; }; |