mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-19 10:53:58 +00:00
- Provide a sysctl interface to change the active system clock at runtime.
- Wrap [get]{bin,nano,micro}[up]time() functions of sys/time.h to allow requesting time from either the feedback or the feed-forward clock. If a feedback (e.g. ntpd) and feed-forward (e.g. radclock) daemon are both running on the system, both kernel clocks are updated but only one serves time. - Add similar wrappers for the feed-forward difference clock. Committed on behalf of Julien Ridoux and Darryl Veitch from the University of Melbourne, Australia, as part of the FreeBSD Foundation funded "Feed-Forward Clock Synchronization Algorithms" project. For more information, see http://www.synclab.org/radclock/ Submitted by: Julien Ridoux (jridoux at unimelb edu au)
This commit is contained in:
parent
b3b514d6ac
commit
9bce0f05fe
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=227747
@ -31,6 +31,8 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/sbuf.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/timeffc.h>
|
#include <sys/timeffc.h>
|
||||||
|
|
||||||
@ -127,3 +129,215 @@ ffclock_difftime(ffcounter ffdelta, struct bintime *bt,
|
|||||||
bintime_mul(error_bound, err_rate * (uint64_t)18446744073709LL);
|
bintime_mul(error_bound, err_rate * (uint64_t)18446744073709LL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sysctl for the Feed-Forward Clock.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int ffclock_version = 2;
|
||||||
|
SYSCTL_NODE(_kern, OID_AUTO, ffclock, CTLFLAG_RW, 0,
|
||||||
|
"Feed-Forward Clock Support");
|
||||||
|
SYSCTL_INT(_kern_ffclock, OID_AUTO, version, CTLFLAG_RD, &ffclock_version, 0,
|
||||||
|
"Version of Feed-Forward Clock Support");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sysctl to select which clock is read when calling any of the
|
||||||
|
* [get]{bin,nano,micro}[up]time() functions.
|
||||||
|
*/
|
||||||
|
char *sysclocks[] = {"feedback", "feed-forward"};
|
||||||
|
|
||||||
|
#define NUM_SYSCLOCKS (sizeof(sysclocks) / sizeof(*sysclocks))
|
||||||
|
|
||||||
|
/* Report or change the active timecounter hardware. */
|
||||||
|
static int
|
||||||
|
sysctl_kern_ffclock_choice(SYSCTL_HANDLER_ARGS)
|
||||||
|
{
|
||||||
|
struct sbuf *s;
|
||||||
|
int clk, error;
|
||||||
|
|
||||||
|
s = sbuf_new_for_sysctl(NULL, NULL, 16 * NUM_SYSCLOCKS, req);
|
||||||
|
if (s == NULL)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
for (clk = 0; clk < NUM_SYSCLOCKS; clk++) {
|
||||||
|
sbuf_cat(s, sysclocks[clk]);
|
||||||
|
if (clk + 1 < NUM_SYSCLOCKS)
|
||||||
|
sbuf_cat(s, " ");
|
||||||
|
}
|
||||||
|
error = sbuf_finish(s);
|
||||||
|
sbuf_delete(s);
|
||||||
|
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYSCTL_PROC(_kern_ffclock, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD,
|
||||||
|
0, 0, sysctl_kern_ffclock_choice, "A", "Clock paradigms available");
|
||||||
|
|
||||||
|
extern int sysclock_active;
|
||||||
|
|
||||||
|
static int
|
||||||
|
sysctl_kern_ffclock_active(SYSCTL_HANDLER_ARGS)
|
||||||
|
{
|
||||||
|
char newclock[32];
|
||||||
|
int error;
|
||||||
|
|
||||||
|
switch (sysclock_active) {
|
||||||
|
case SYSCLOCK_FBCK:
|
||||||
|
strlcpy(newclock, sysclocks[SYSCLOCK_FBCK], sizeof(newclock));
|
||||||
|
break;
|
||||||
|
case SYSCLOCK_FFWD:
|
||||||
|
strlcpy(newclock, sysclocks[SYSCLOCK_FFWD], sizeof(newclock));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = sysctl_handle_string(oidp, &newclock[0], sizeof(newclock), req);
|
||||||
|
if (error != 0 || req->newptr == NULL)
|
||||||
|
return (error);
|
||||||
|
if (strncmp(newclock, sysclocks[SYSCLOCK_FBCK],
|
||||||
|
sizeof(sysclocks[SYSCLOCK_FBCK])) == 0)
|
||||||
|
sysclock_active = SYSCLOCK_FBCK;
|
||||||
|
else if (strncmp(newclock, sysclocks[SYSCLOCK_FFWD],
|
||||||
|
sizeof(sysclocks[SYSCLOCK_FFWD])) == 0)
|
||||||
|
sysclock_active = SYSCLOCK_FFWD;
|
||||||
|
else
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
SYSCTL_PROC(_kern_ffclock, OID_AUTO, active, CTLTYPE_STRING | CTLFLAG_RW,
|
||||||
|
0, 0, sysctl_kern_ffclock_active, "A", "Kernel clock selected");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* High level functions to access the Feed-Forward Clock.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ffclock_bintime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_nanotime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC);
|
||||||
|
bintime2timespec(&bt, tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_microtime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC);
|
||||||
|
bintime2timeval(&bt, tvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_getbintime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, bt, NULL,
|
||||||
|
FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_getnanotime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, &bt, NULL,
|
||||||
|
FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST);
|
||||||
|
bintime2timespec(&bt, tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_getmicrotime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, &bt, NULL,
|
||||||
|
FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST);
|
||||||
|
bintime2timeval(&bt, tvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_binuptime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_nanouptime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME);
|
||||||
|
bintime2timespec(&bt, tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_microuptime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME);
|
||||||
|
bintime2timeval(&bt, tvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_getbinuptime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, bt, NULL,
|
||||||
|
FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_getnanouptime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, &bt, NULL,
|
||||||
|
FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST);
|
||||||
|
bintime2timespec(&bt, tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_getmicrouptime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
ffclock_abstime(NULL, &bt, NULL,
|
||||||
|
FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST);
|
||||||
|
bintime2timeval(&bt, tvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_bindifftime(ffcounter ffdelta, struct bintime *bt)
|
||||||
|
{
|
||||||
|
|
||||||
|
ffclock_difftime(ffdelta, bt, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_nanodifftime(ffcounter ffdelta, struct timespec *tsp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
ffclock_difftime(ffdelta, &bt, NULL);
|
||||||
|
bintime2timespec(&bt, tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ffclock_microdifftime(ffcounter ffdelta, struct timeval *tvp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
ffclock_difftime(ffdelta, &bt, NULL);
|
||||||
|
bintime2timeval(&bt, tvp);
|
||||||
|
}
|
||||||
|
@ -177,6 +177,144 @@ tc_delta(struct timehands *th)
|
|||||||
* the comment in <sys/time.h> for a description of these 12 functions.
|
* the comment in <sys/time.h> for a description of these 12 functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef FFCLOCK
|
||||||
|
static void
|
||||||
|
fbclock_binuptime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
struct timehands *th;
|
||||||
|
unsigned int gen;
|
||||||
|
|
||||||
|
do {
|
||||||
|
th = timehands;
|
||||||
|
gen = th->th_generation;
|
||||||
|
*bt = th->th_offset;
|
||||||
|
bintime_addx(bt, th->th_scale * tc_delta(th));
|
||||||
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_nanouptime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
binuptime(&bt);
|
||||||
|
bintime2timespec(&bt, tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_microuptime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
binuptime(&bt);
|
||||||
|
bintime2timeval(&bt, tvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_bintime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
|
||||||
|
binuptime(bt);
|
||||||
|
bintime_add(bt, &boottimebin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_nanotime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
bintime(&bt);
|
||||||
|
bintime2timespec(&bt, tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_microtime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
struct bintime bt;
|
||||||
|
|
||||||
|
bintime(&bt);
|
||||||
|
bintime2timeval(&bt, tvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_getbinuptime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
struct timehands *th;
|
||||||
|
unsigned int gen;
|
||||||
|
|
||||||
|
do {
|
||||||
|
th = timehands;
|
||||||
|
gen = th->th_generation;
|
||||||
|
*bt = th->th_offset;
|
||||||
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_getnanouptime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
struct timehands *th;
|
||||||
|
unsigned int gen;
|
||||||
|
|
||||||
|
do {
|
||||||
|
th = timehands;
|
||||||
|
gen = th->th_generation;
|
||||||
|
bintime2timespec(&th->th_offset, tsp);
|
||||||
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_getmicrouptime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
struct timehands *th;
|
||||||
|
unsigned int gen;
|
||||||
|
|
||||||
|
do {
|
||||||
|
th = timehands;
|
||||||
|
gen = th->th_generation;
|
||||||
|
bintime2timeval(&th->th_offset, tvp);
|
||||||
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_getbintime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
struct timehands *th;
|
||||||
|
unsigned int gen;
|
||||||
|
|
||||||
|
do {
|
||||||
|
th = timehands;
|
||||||
|
gen = th->th_generation;
|
||||||
|
*bt = th->th_offset;
|
||||||
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
|
bintime_add(bt, &boottimebin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_getnanotime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
struct timehands *th;
|
||||||
|
unsigned int gen;
|
||||||
|
|
||||||
|
do {
|
||||||
|
th = timehands;
|
||||||
|
gen = th->th_generation;
|
||||||
|
*tsp = th->th_nanotime;
|
||||||
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fbclock_getmicrotime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
struct timehands *th;
|
||||||
|
unsigned int gen;
|
||||||
|
|
||||||
|
do {
|
||||||
|
th = timehands;
|
||||||
|
gen = th->th_generation;
|
||||||
|
*tvp = th->th_microtime;
|
||||||
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
|
}
|
||||||
|
#else /* !FFCLOCK */
|
||||||
void
|
void
|
||||||
binuptime(struct bintime *bt)
|
binuptime(struct bintime *bt)
|
||||||
{
|
{
|
||||||
@ -313,6 +451,7 @@ getmicrotime(struct timeval *tvp)
|
|||||||
*tvp = th->th_microtime;
|
*tvp = th->th_microtime;
|
||||||
} while (gen == 0 || gen != th->th_generation);
|
} while (gen == 0 || gen != th->th_generation);
|
||||||
}
|
}
|
||||||
|
#endif /* FFCLOCK */
|
||||||
|
|
||||||
#ifdef FFCLOCK
|
#ifdef FFCLOCK
|
||||||
/*
|
/*
|
||||||
@ -322,6 +461,8 @@ getmicrotime(struct timeval *tvp)
|
|||||||
* necessary.
|
* necessary.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int sysclock_active = SYSCLOCK_FBCK;
|
||||||
|
|
||||||
/* Feed-forward clock estimates kept updated by the synchronization daemon. */
|
/* Feed-forward clock estimates kept updated by the synchronization daemon. */
|
||||||
struct ffclock_estimate ffclock_estimate;
|
struct ffclock_estimate ffclock_estimate;
|
||||||
struct bintime ffclock_boottime; /* Feed-forward boot time estimate. */
|
struct bintime ffclock_boottime; /* Feed-forward boot time estimate. */
|
||||||
@ -329,6 +470,38 @@ uint32_t ffclock_status; /* Feed-forward clock status. */
|
|||||||
int8_t ffclock_updated; /* New estimates are available. */
|
int8_t ffclock_updated; /* New estimates are available. */
|
||||||
struct mtx ffclock_mtx; /* Mutex on ffclock_estimate. */
|
struct mtx ffclock_mtx; /* Mutex on ffclock_estimate. */
|
||||||
|
|
||||||
|
struct sysclock_ops {
|
||||||
|
int active;
|
||||||
|
void (*binuptime) (struct bintime *bt);
|
||||||
|
void (*nanouptime) (struct timespec *tsp);
|
||||||
|
void (*microuptime) (struct timeval *tvp);
|
||||||
|
void (*bintime) (struct bintime *bt);
|
||||||
|
void (*nanotime) (struct timespec *tsp);
|
||||||
|
void (*microtime) (struct timeval *tvp);
|
||||||
|
void (*getbinuptime) (struct bintime *bt);
|
||||||
|
void (*getnanouptime) (struct timespec *tsp);
|
||||||
|
void (*getmicrouptime) (struct timeval *tvp);
|
||||||
|
void (*getbintime) (struct bintime *bt);
|
||||||
|
void (*getnanotime) (struct timespec *tsp);
|
||||||
|
void (*getmicrotime) (struct timeval *tvp);
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sysclock_ops sysclock = {
|
||||||
|
.active = SYSCLOCK_FBCK,
|
||||||
|
.binuptime = fbclock_binuptime,
|
||||||
|
.nanouptime = fbclock_nanouptime,
|
||||||
|
.microuptime = fbclock_microuptime,
|
||||||
|
.bintime = fbclock_bintime,
|
||||||
|
.nanotime = fbclock_nanotime,
|
||||||
|
.microtime = fbclock_microtime,
|
||||||
|
.getbinuptime = fbclock_getbinuptime,
|
||||||
|
.getnanouptime = fbclock_getnanouptime,
|
||||||
|
.getmicrouptime = fbclock_getmicrouptime,
|
||||||
|
.getbintime = fbclock_getbintime,
|
||||||
|
.getnanotime = fbclock_getnanotime,
|
||||||
|
.getmicrotime = fbclock_getmicrotime
|
||||||
|
};
|
||||||
|
|
||||||
struct fftimehands {
|
struct fftimehands {
|
||||||
struct ffclock_estimate cest;
|
struct ffclock_estimate cest;
|
||||||
struct bintime tick_time;
|
struct bintime tick_time;
|
||||||
@ -621,6 +794,46 @@ ffclock_change_tc(struct timehands *th)
|
|||||||
fftimehands = ffth;
|
fftimehands = ffth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
change_sysclock(int new_sysclock)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.active = new_sysclock;
|
||||||
|
|
||||||
|
switch (sysclock.active) {
|
||||||
|
case SYSCLOCK_FBCK:
|
||||||
|
sysclock.binuptime = fbclock_binuptime;
|
||||||
|
sysclock.nanouptime = fbclock_nanouptime;
|
||||||
|
sysclock.microuptime = fbclock_microuptime;
|
||||||
|
sysclock.bintime = fbclock_bintime;
|
||||||
|
sysclock.nanotime = fbclock_nanotime;
|
||||||
|
sysclock.microtime = fbclock_microtime;
|
||||||
|
sysclock.getbinuptime = fbclock_getbinuptime;
|
||||||
|
sysclock.getnanouptime = fbclock_getnanouptime;
|
||||||
|
sysclock.getmicrouptime = fbclock_getmicrouptime;
|
||||||
|
sysclock.getbintime = fbclock_getbintime;
|
||||||
|
sysclock.getnanotime = fbclock_getnanotime;
|
||||||
|
sysclock.getmicrotime = fbclock_getmicrotime;
|
||||||
|
break;
|
||||||
|
case SYSCLOCK_FFWD:
|
||||||
|
sysclock.binuptime = ffclock_binuptime;
|
||||||
|
sysclock.nanouptime = ffclock_nanouptime;
|
||||||
|
sysclock.microuptime = ffclock_microuptime;
|
||||||
|
sysclock.bintime = ffclock_bintime;
|
||||||
|
sysclock.nanotime = ffclock_nanotime;
|
||||||
|
sysclock.microtime = ffclock_microtime;
|
||||||
|
sysclock.getbinuptime = ffclock_getbinuptime;
|
||||||
|
sysclock.getnanouptime = ffclock_getnanouptime;
|
||||||
|
sysclock.getmicrouptime = ffclock_getmicrouptime;
|
||||||
|
sysclock.getbintime = ffclock_getbintime;
|
||||||
|
sysclock.getnanotime = ffclock_getnanotime;
|
||||||
|
sysclock.getmicrotime = ffclock_getmicrotime;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retrieve feed-forward counter and time of last kernel tick.
|
* Retrieve feed-forward counter and time of last kernel tick.
|
||||||
*/
|
*/
|
||||||
@ -731,6 +944,90 @@ ffclock_read_counter(ffcounter *ffcount)
|
|||||||
|
|
||||||
*ffcount += delta;
|
*ffcount += delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
binuptime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.binuptime(bt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nanouptime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.nanouptime(tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
microuptime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.microuptime(tvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
bintime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.bintime(bt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nanotime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.nanotime(tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
microtime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.microtime(tvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getbinuptime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.getbinuptime(bt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getnanouptime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.getnanouptime(tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getmicrouptime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.getmicrouptime(tvp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getbintime(struct bintime *bt)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.getbintime(bt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getnanotime(struct timespec *tsp)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.getnanotime(tsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getmicrotime(struct timeval *tvp)
|
||||||
|
{
|
||||||
|
|
||||||
|
sysclock.getmicrouptime(tvp);
|
||||||
|
}
|
||||||
#endif /* FFCLOCK */
|
#endif /* FFCLOCK */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -971,6 +1268,11 @@ tc_windup(void)
|
|||||||
scale /= th->th_counter->tc_frequency;
|
scale /= th->th_counter->tc_frequency;
|
||||||
th->th_scale = scale * 2;
|
th->th_scale = scale * 2;
|
||||||
|
|
||||||
|
#ifdef FFCLOCK
|
||||||
|
if (sysclock_active != sysclock.active)
|
||||||
|
change_sysclock(sysclock_active);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that the struct timehands is again consistent, set the new
|
* Now that the struct timehands is again consistent, set the new
|
||||||
* generation number, making sure to not make it zero.
|
* generation number, making sure to not make it zero.
|
||||||
@ -980,8 +1282,21 @@ tc_windup(void)
|
|||||||
th->th_generation = ogen;
|
th->th_generation = ogen;
|
||||||
|
|
||||||
/* Go live with the new struct timehands. */
|
/* Go live with the new struct timehands. */
|
||||||
time_second = th->th_microtime.tv_sec;
|
#ifdef FFCLOCK
|
||||||
time_uptime = th->th_offset.sec;
|
switch (sysclock_active) {
|
||||||
|
case SYSCLOCK_FBCK:
|
||||||
|
#endif
|
||||||
|
time_second = th->th_microtime.tv_sec;
|
||||||
|
time_uptime = th->th_offset.sec;
|
||||||
|
#ifdef FFCLOCK
|
||||||
|
break;
|
||||||
|
case SYSCLOCK_FFWD:
|
||||||
|
time_second = fftimehands->tick_time_lerp.sec;
|
||||||
|
time_uptime = fftimehands->tick_time_lerp.sec - ffclock_boottime.sec;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
timehands = th;
|
timehands = th;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1261,6 +1576,7 @@ inittimecounter(void *dummy)
|
|||||||
|
|
||||||
#ifdef FFCLOCK
|
#ifdef FFCLOCK
|
||||||
ffclock_init();
|
ffclock_init();
|
||||||
|
change_sysclock(sysclock_active);
|
||||||
#endif
|
#endif
|
||||||
/* warm up new timecounter (again) and get rolling. */
|
/* warm up new timecounter (again) and get rolling. */
|
||||||
(void)timecounter->tc_get_timecount(timecounter);
|
(void)timecounter->tc_get_timecount(timecounter);
|
||||||
|
@ -55,6 +55,13 @@ struct ffclock_estimate {
|
|||||||
#if __BSD_VISIBLE
|
#if __BSD_VISIBLE
|
||||||
#ifdef _KERNEL
|
#ifdef _KERNEL
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Index into the sysclocks array for obtaining the ASCII name of a particular
|
||||||
|
* sysclock.
|
||||||
|
*/
|
||||||
|
#define SYSCLOCK_FBCK 0
|
||||||
|
#define SYSCLOCK_FFWD 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parameters of counter characterisation required by feed-forward algorithms.
|
* Parameters of counter characterisation required by feed-forward algorithms.
|
||||||
*/
|
*/
|
||||||
@ -128,6 +135,35 @@ void ffclock_abstime(ffcounter *ffcount, struct bintime *bt,
|
|||||||
void ffclock_difftime(ffcounter ffdelta, struct bintime *bt,
|
void ffclock_difftime(ffcounter ffdelta, struct bintime *bt,
|
||||||
struct bintime *error_bound);
|
struct bintime *error_bound);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper routines to return current absolute time using the feed-forward
|
||||||
|
* clock. These functions are named after those defined in <sys/time.h>, which
|
||||||
|
* contains a description of the original ones.
|
||||||
|
*/
|
||||||
|
void ffclock_bintime(struct bintime *bt);
|
||||||
|
void ffclock_nanotime(struct timespec *tsp);
|
||||||
|
void ffclock_microtime(struct timeval *tvp);
|
||||||
|
|
||||||
|
void ffclock_getbintime(struct bintime *bt);
|
||||||
|
void ffclock_getnanotime(struct timespec *tsp);
|
||||||
|
void ffclock_getmicrotime(struct timeval *tvp);
|
||||||
|
|
||||||
|
void ffclock_binuptime(struct bintime *bt);
|
||||||
|
void ffclock_nanouptime(struct timespec *tsp);
|
||||||
|
void ffclock_microuptime(struct timeval *tvp);
|
||||||
|
|
||||||
|
void ffclock_getbinuptime(struct bintime *bt);
|
||||||
|
void ffclock_getnanouptime(struct timespec *tsp);
|
||||||
|
void ffclock_getmicrouptime(struct timeval *tvp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper routines to convert a time interval specified in ffcounter units into
|
||||||
|
* seconds using the current feed-forward clock estimates.
|
||||||
|
*/
|
||||||
|
void ffclock_bindifftime(ffcounter ffdelta, struct bintime *bt);
|
||||||
|
void ffclock_nanodifftime(ffcounter ffdelta, struct timespec *tsp);
|
||||||
|
void ffclock_microdifftime(ffcounter ffdelta, struct timeval *tvp);
|
||||||
|
|
||||||
#endif /* _KERNEL */
|
#endif /* _KERNEL */
|
||||||
#endif /* __BSD_VISIBLE */
|
#endif /* __BSD_VISIBLE */
|
||||||
#endif /* _SYS_TIMEFF_H_ */
|
#endif /* _SYS_TIMEFF_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user