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
This commit is contained in:
parent
e9bd3a37e8
commit
6b6ef746e5
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=48887
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user