- Add the ffclock_getcounter(), ffclock_getestimate() and ffclock_setestimate()
system calls to provide feed-forward clock management capabilities to userspace processes. ffclock_getcounter() returns the current value of the kernel's feed-forward clock counter. ffclock_getestimate() returns the current feed-forward clock parameter estimates and ffclock_setestimate() updates the feed-forward clock parameter estimates. - Document the syscalls in the ffclock.2 man page. - Regenerate the script-derived syscall related files. 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
ebcc5e9a0d
commit
cf13a58510
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=227776
@ -80,7 +80,7 @@ MAN+= abort2.2 accept.2 access.2 acct.2 adjtime.2 \
|
||||
bind.2 brk.2 cap_enter.2 cap_new.2 chdir.2 chflags.2 \
|
||||
chmod.2 chown.2 chroot.2 clock_gettime.2 close.2 closefrom.2 \
|
||||
connect.2 cpuset.2 cpuset_getaffinity.2 dup.2 execve.2 _exit.2 \
|
||||
extattr_get_file.2 fcntl.2 fhopen.2 flock.2 fork.2 fsync.2 \
|
||||
extattr_get_file.2 fcntl.2 ffclock.2 fhopen.2 flock.2 fork.2 fsync.2 \
|
||||
getdirentries.2 getdtablesize.2 \
|
||||
getfh.2 getfsstat.2 getgid.2 getgroups.2 getitimer.2 getlogin.2 \
|
||||
getloginclass.2 getpeername.2 getpgrp.2 getpid.2 getpriority.2 \
|
||||
@ -142,6 +142,8 @@ MLINKS+=extattr_get_file.2 extattr.2 \
|
||||
extattr_get_file.2 extattr_set_fd.2 \
|
||||
extattr_get_file.2 extattr_set_file.2 \
|
||||
extattr_get_file.2 extattr_set_link.2
|
||||
MLINKS+=ffclock.2 ffclock_getcounter.2 ffclock.2 ffclock_getestimate.2 \
|
||||
ffclock.2 ffclock_setestimate.2
|
||||
MLINKS+=fhopen.2 fhstat.2 fhopen.2 fhstatfs.2
|
||||
MLINKS+=getdirentries.2 getdents.2
|
||||
MLINKS+=getfh.2 lgetfh.2
|
||||
|
@ -365,6 +365,9 @@ FBSD_1.2 {
|
||||
cap_getmode;
|
||||
cap_new;
|
||||
cap_getrights;
|
||||
ffclock_getcounter;
|
||||
ffclock_getestimate;
|
||||
ffclock_setestimate;
|
||||
getloginclass;
|
||||
pdfork;
|
||||
pdgetpid;
|
||||
|
177
lib/libc/sys/ffclock.2
Normal file
177
lib/libc/sys/ffclock.2
Normal file
@ -0,0 +1,177 @@
|
||||
.\" Copyright (c) 2011 The University of Melbourne
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This documentation was written by Julien Ridoux at the University of
|
||||
.\" Melbourne under sponsorship from the FreeBSD Foundation.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 21, 2011
|
||||
.Dt FFCLOCK 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ffclock_getcounter ,
|
||||
.Nm ffclock_getestimate ,
|
||||
.Nm ffclock_setestimate
|
||||
.Nd Retrieve feed-forward counter, get and set feed-forward clock estimates.
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In sys/timeffc.h
|
||||
.Ft int
|
||||
.Fn ffclock_getcounter "ffcounter *ffcount"
|
||||
.Ft int
|
||||
.Fn ffclock_getestimate "struct ffclock_estimate *cest"
|
||||
.Ft int
|
||||
.Fn ffclock_setestimate "struct ffclock_estimate *cest"
|
||||
.Sh DESCRIPTION
|
||||
The ffclock is an alternative method to synchronise the system clock.
|
||||
The ffclock implements a feed-forward paradigm and decouples the timestamping
|
||||
and timekeeping kernel functions.
|
||||
This ensures that past clock errors do not affect current timekeeping, an
|
||||
approach radically different from the feedback alternative implemented by the
|
||||
ntpd daemon when adjusting the system clock.
|
||||
The feed-forward approach has demonstrated better performance and higher
|
||||
robustness than a feedback approach when synchronising over the network.
|
||||
.Pp
|
||||
In the feed-forward context, a
|
||||
.Em timestamp
|
||||
is a cumulative value of the ticks of the timecounter, which can be converted
|
||||
into seconds by using the feed-forward
|
||||
.Em clock estimates.
|
||||
.Pp
|
||||
The
|
||||
.Fn ffclock_getcounter
|
||||
system call allows the calling process to retrieve the current value of the
|
||||
feed-forward counter maintained by the kernel.
|
||||
.Pp
|
||||
The
|
||||
.Fn ffclock_getestimate
|
||||
and
|
||||
.Fn ffclock_setestimate
|
||||
system calls allow the caller to get and set the kernel's feed-forward clock
|
||||
parameter estimates respectively.
|
||||
The
|
||||
.Fn ffclock_setestimate
|
||||
system call should be invoked by a single instance of a feed-forward
|
||||
synchronisation daemon.
|
||||
The
|
||||
.Fn ffclock_getestimate
|
||||
system call can be called by any process to retrieve the feed-forward clock
|
||||
estimates.
|
||||
.Pp
|
||||
The feed-forward approach does not require that the clock estimates be retrieved
|
||||
every time a timestamp is to be converted into seconds.
|
||||
The number of system calls can therefore be greatly reduced if the calling
|
||||
process retrieves the clock estimates from the clock synchronisation daemon
|
||||
instead.
|
||||
The
|
||||
.Fn ffclock_getestimate
|
||||
must be used when the feed-forward synchronisation daemon is not running
|
||||
.Po see
|
||||
.Sx USAGE
|
||||
below
|
||||
.Pc .
|
||||
.Pp
|
||||
The clock parameter estimates structure pointed to by
|
||||
.Fa cest
|
||||
is defined in
|
||||
.In sys/timeffc.h
|
||||
as:
|
||||
.Bd -literal
|
||||
struct ffclock_estimate {
|
||||
struct bintime update_time; /* Time of last estimates update. */
|
||||
ffcounter update_ffcount; /* Counter value at last update. */
|
||||
ffcounter leapsec_next; /* Counter value of next leap second. */
|
||||
uint64_t period; /* Estimate of counter period. */
|
||||
uint32_t errb_abs; /* Bound on absolute clock error [ns]. */
|
||||
uint32_t errb_rate; /* Bound on counter rate error [ps/s]. */
|
||||
uint32_t status; /* Clock status. */
|
||||
int16_t leapsec_total; /* All leap seconds seen so far. */
|
||||
int8_t leapsec; /* Next leap second (in {-1,0,1}). */
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
Only the super-user may set the feed-forward clock estimates.
|
||||
.Sh RETURN VALUES
|
||||
.Rv -std
|
||||
.Sh ERRORS
|
||||
The following error codes may be set in
|
||||
.Va errno :
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EFAULT
|
||||
The
|
||||
.Fa ffcount
|
||||
or
|
||||
.Fa cest
|
||||
pointer referenced invalid memory.
|
||||
.It Bq Er EPERM
|
||||
A user other than the super-user attempted to set the feed-forward clock
|
||||
parameter estimates.
|
||||
.El
|
||||
.Sh USAGE
|
||||
The feed-forward paradigm enables the definition of specialised clock functions.
|
||||
.Pp
|
||||
In its simplest form,
|
||||
.Fn ffclock_getcounter
|
||||
can be used to establish strict order between events or to measure small time
|
||||
intervals very accurately with a minimum performance cost.
|
||||
.Pp
|
||||
Different methods exist to access absolute time
|
||||
.Po or
|
||||
.Qq wall-clock time
|
||||
.Pc tracked by the ffclock.
|
||||
The simplest method uses the ffclock sysctl interface
|
||||
.Va kern.ffclock
|
||||
to make the system clock return the ffclock time.
|
||||
The
|
||||
.Xr clock_gettime 2
|
||||
system call can then be used to retrieve the current time seen by the
|
||||
feed-forward clock.
|
||||
Note that this setting affects the entire system and that a feed-forward
|
||||
synchronisation daemon should be running.
|
||||
.Pp
|
||||
A less automated method consists of retrieving the feed-forward counter
|
||||
timestamp from the kernel and using the feed-forward clock parameter estimates
|
||||
to convert the timestamp into seconds.
|
||||
The feed-forward clock parameter estimates can be retrieved from the kernel or
|
||||
from the synchronisation daemon directly (preferred).
|
||||
This method allows converting timestamps using different clock models as needed
|
||||
by the application, while collecting meaningful upper bounds on current clock
|
||||
error.
|
||||
.Sh SEE ALSO
|
||||
.Xr date 1 ,
|
||||
.Xr adjtime 2 ,
|
||||
.Xr clock_gettime 2 ,
|
||||
.Xr ctime 3
|
||||
.Sh HISTORY
|
||||
Feed-forward clock support first appeared in
|
||||
.Fx 10.0 .
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
The feed-forward clock support was written by
|
||||
.An Julien Ridoux Aq jridoux@unimelb.edu.au
|
||||
in collaboration with
|
||||
.An Darryl Veitch Aq dveitch@unimelb.edu.au
|
||||
at the University of Melbourne under sponsorship from the FreeBSD Foundation.
|
@ -12,6 +12,7 @@
|
||||
#include <sys/signal.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/_ffcounter.h>
|
||||
#include <sys/_semaphore.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <sys/signal.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/_ffcounter.h>
|
||||
#include <sys/_semaphore.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
|
@ -207,6 +207,9 @@
|
||||
#define FREEBSD32_SYS_freebsd32_clock_settime 233
|
||||
#define FREEBSD32_SYS_freebsd32_clock_getres 234
|
||||
#define FREEBSD32_SYS_freebsd32_nanosleep 240
|
||||
#define FREEBSD32_SYS_ffclock_getcounter 241
|
||||
#define FREEBSD32_SYS_ffclock_setestimate 242
|
||||
#define FREEBSD32_SYS_ffclock_getestimate 243
|
||||
#define FREEBSD32_SYS_minherit 250
|
||||
#define FREEBSD32_SYS_rfork 251
|
||||
#define FREEBSD32_SYS_openbsd_poll 252
|
||||
|
@ -251,9 +251,9 @@ const char *freebsd32_syscallnames[] = {
|
||||
"#238", /* 238 = timer_gettime */
|
||||
"#239", /* 239 = timer_getoverrun */
|
||||
"freebsd32_nanosleep", /* 240 = freebsd32_nanosleep */
|
||||
"#241", /* 241 = nosys */
|
||||
"#242", /* 242 = nosys */
|
||||
"#243", /* 243 = nosys */
|
||||
"ffclock_getcounter", /* 241 = ffclock_getcounter */
|
||||
"ffclock_setestimate", /* 242 = ffclock_setestimate */
|
||||
"ffclock_getestimate", /* 243 = ffclock_getestimate */
|
||||
"#244", /* 244 = nosys */
|
||||
"#245", /* 245 = nosys */
|
||||
"#246", /* 246 = nosys */
|
||||
|
@ -288,9 +288,9 @@ struct sysent freebsd32_sysent[] = {
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 238 = timer_gettime */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 239 = timer_getoverrun */
|
||||
{ AS(freebsd32_nanosleep_args), (sy_call_t *)freebsd32_nanosleep, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 240 = freebsd32_nanosleep */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 241 = nosys */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 242 = nosys */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 243 = nosys */
|
||||
{ AS(ffclock_getcounter_args), (sy_call_t *)sys_ffclock_getcounter, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 241 = ffclock_getcounter */
|
||||
{ AS(ffclock_setestimate_args), (sy_call_t *)sys_ffclock_setestimate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 242 = ffclock_setestimate */
|
||||
{ AS(ffclock_getestimate_args), (sy_call_t *)sys_ffclock_getestimate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 243 = ffclock_getestimate */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 244 = nosys */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 245 = nosys */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 246 = nosys */
|
||||
|
@ -1203,6 +1203,27 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* ffclock_getcounter */
|
||||
case 241: {
|
||||
struct ffclock_getcounter_args *p = params;
|
||||
uarg[0] = (intptr_t) p->ffcount; /* ffcounter * */
|
||||
*n_args = 1;
|
||||
break;
|
||||
}
|
||||
/* ffclock_setestimate */
|
||||
case 242: {
|
||||
struct ffclock_setestimate_args *p = params;
|
||||
uarg[0] = (intptr_t) p->cest; /* struct ffclock_estimate * */
|
||||
*n_args = 1;
|
||||
break;
|
||||
}
|
||||
/* ffclock_getestimate */
|
||||
case 243: {
|
||||
struct ffclock_getestimate_args *p = params;
|
||||
uarg[0] = (intptr_t) p->cest; /* struct ffclock_estimate * */
|
||||
*n_args = 1;
|
||||
break;
|
||||
}
|
||||
/* minherit */
|
||||
case 250: {
|
||||
struct minherit_args *p = params;
|
||||
@ -4940,6 +4961,36 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* ffclock_getcounter */
|
||||
case 241:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "ffcounter *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* ffclock_setestimate */
|
||||
case 242:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "struct ffclock_estimate *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* ffclock_getestimate */
|
||||
case 243:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "struct ffclock_estimate *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* minherit */
|
||||
case 250:
|
||||
switch(ndx) {
|
||||
@ -8824,6 +8875,21 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* ffclock_getcounter */
|
||||
case 241:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* ffclock_setestimate */
|
||||
case 242:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* ffclock_getestimate */
|
||||
case 243:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* minherit */
|
||||
case 250:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
|
@ -447,9 +447,11 @@
|
||||
240 AUE_NULL STD { int freebsd32_nanosleep( \
|
||||
const struct timespec32 *rqtp, \
|
||||
struct timespec32 *rmtp); }
|
||||
241 AUE_NULL UNIMPL nosys
|
||||
242 AUE_NULL UNIMPL nosys
|
||||
243 AUE_NULL UNIMPL nosys
|
||||
241 AUE_NULL NOPROTO { int ffclock_getcounter(ffcounter *ffcount); }
|
||||
242 AUE_NULL NOPROTO { int ffclock_setestimate( \
|
||||
struct ffclock_estimate *cest); }
|
||||
243 AUE_NULL NOPROTO { int ffclock_getestimate( \
|
||||
struct ffclock_estimate *cest); }
|
||||
244 AUE_NULL UNIMPL nosys
|
||||
245 AUE_NULL UNIMPL nosys
|
||||
246 AUE_NULL UNIMPL nosys
|
||||
|
@ -2341,7 +2341,7 @@ kern/kern_event.c standard
|
||||
kern/kern_exec.c standard
|
||||
kern/kern_exit.c standard
|
||||
kern/kern_fail.c standard
|
||||
kern/kern_ffclock.c optional ffclock
|
||||
kern/kern_ffclock.c standard
|
||||
kern/kern_fork.c standard
|
||||
kern/kern_gzio.c optional gzio
|
||||
kern/kern_hhook.c standard
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <sys/signal.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/_ffcounter.h>
|
||||
#include <sys/_semaphore.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
|
@ -275,9 +275,9 @@ struct sysent sysent[] = {
|
||||
{ AS(ktimer_gettime_args), (sy_call_t *)sys_ktimer_gettime, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 238 = ktimer_gettime */
|
||||
{ AS(ktimer_getoverrun_args), (sy_call_t *)sys_ktimer_getoverrun, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 239 = ktimer_getoverrun */
|
||||
{ AS(nanosleep_args), (sy_call_t *)sys_nanosleep, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 240 = nanosleep */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 241 = nosys */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 242 = nosys */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 243 = nosys */
|
||||
{ AS(ffclock_getcounter_args), (sy_call_t *)sys_ffclock_getcounter, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 241 = ffclock_getcounter */
|
||||
{ AS(ffclock_setestimate_args), (sy_call_t *)sys_ffclock_setestimate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 242 = ffclock_setestimate */
|
||||
{ AS(ffclock_getestimate_args), (sy_call_t *)sys_ffclock_getestimate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 243 = ffclock_getestimate */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 244 = nosys */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 245 = nosys */
|
||||
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 246 = nosys */
|
||||
|
@ -30,14 +30,29 @@
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "opt_ffclock.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/sysent.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/timeffc.h>
|
||||
|
||||
#ifdef FFCLOCK
|
||||
|
||||
extern struct ffclock_estimate ffclock_estimate;
|
||||
extern struct bintime ffclock_boottime;
|
||||
extern int8_t ffclock_updated;
|
||||
extern struct mtx ffclock_mtx;
|
||||
|
||||
/*
|
||||
* Feed-forward clock absolute time. This should be the preferred way to read
|
||||
@ -208,6 +223,12 @@ sysctl_kern_ffclock_active(SYSCTL_HANDLER_ARGS)
|
||||
SYSCTL_PROC(_kern_ffclock, OID_AUTO, active, CTLTYPE_STRING | CTLFLAG_RW,
|
||||
0, 0, sysctl_kern_ffclock_active, "A", "Kernel clock selected");
|
||||
|
||||
int sysctl_kern_ffclock_ffcounter_bypass = 0;
|
||||
|
||||
SYSCTL_INT(_kern_ffclock, OID_AUTO, ffcounter_bypass, CTLFLAG_RW,
|
||||
&sysctl_kern_ffclock_ffcounter_bypass, 0,
|
||||
"Use reliable hardware timecounter as the Feed-Forward Counter");
|
||||
|
||||
/*
|
||||
* High level functions to access the Feed-Forward Clock.
|
||||
*/
|
||||
@ -341,3 +362,112 @@ ffclock_microdifftime(ffcounter ffdelta, struct timeval *tvp)
|
||||
ffclock_difftime(ffdelta, &bt, NULL);
|
||||
bintime2timeval(&bt, tvp);
|
||||
}
|
||||
|
||||
/*
|
||||
* System call allowing userland applications to retrieve the current value of
|
||||
* the Feed-Forward Clock counter.
|
||||
*/
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct ffclock_getcounter_args {
|
||||
ffcounter *ffcount;
|
||||
};
|
||||
#endif
|
||||
/* ARGSUSED */
|
||||
int
|
||||
sys_ffclock_getcounter(struct thread *td, struct ffclock_getcounter_args *uap)
|
||||
{
|
||||
ffcounter ffcount;
|
||||
int error;
|
||||
|
||||
ffcount = 0;
|
||||
ffclock_read_counter(&ffcount);
|
||||
if (ffcount == 0)
|
||||
return (EAGAIN);
|
||||
error = copyout(&ffcount, uap->ffcount, sizeof(ffcounter));
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* System call allowing the synchronisation daemon to push new feed-foward clock
|
||||
* estimates to the kernel. Acquire ffclock_mtx to prevent concurrent updates
|
||||
* and ensure data consistency.
|
||||
* NOTE: ffclock_updated signals the fftimehands that new estimates are
|
||||
* available. The updated estimates are picked up by the fftimehands on next
|
||||
* tick, which could take as long as 1/hz seconds (if ticks are not missed).
|
||||
*/
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct ffclock_setestimate_args {
|
||||
struct ffclock_estimate *cest;
|
||||
};
|
||||
#endif
|
||||
/* ARGSUSED */
|
||||
int
|
||||
sys_ffclock_setestimate(struct thread *td, struct ffclock_setestimate_args *uap)
|
||||
{
|
||||
struct ffclock_estimate cest;
|
||||
int error;
|
||||
|
||||
/* Reuse of PRIV_CLOCK_SETTIME. */
|
||||
if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0)
|
||||
return (error);
|
||||
|
||||
if ((error = copyin(uap->cest, &cest, sizeof(struct ffclock_estimate)))
|
||||
!= 0)
|
||||
return (error);
|
||||
|
||||
mtx_lock(&ffclock_mtx);
|
||||
memcpy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate));
|
||||
ffclock_updated++;
|
||||
mtx_unlock(&ffclock_mtx);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* System call allowing userland applications to retrieve the clock estimates
|
||||
* stored within the kernel. It is useful to kickstart the synchronisation
|
||||
* daemon with the kernel's knowledge of hardware timecounter.
|
||||
*/
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct ffclock_getestimate_args {
|
||||
struct ffclock_estimate *cest;
|
||||
};
|
||||
#endif
|
||||
/* ARGSUSED */
|
||||
int
|
||||
sys_ffclock_getestimate(struct thread *td, struct ffclock_getestimate_args *uap)
|
||||
{
|
||||
struct ffclock_estimate cest;
|
||||
int error;
|
||||
|
||||
mtx_lock(&ffclock_mtx);
|
||||
memcpy(&cest, &ffclock_estimate, sizeof(struct ffclock_estimate));
|
||||
mtx_unlock(&ffclock_mtx);
|
||||
error = copyout(&cest, uap->cest, sizeof(struct ffclock_estimate));
|
||||
return (error);
|
||||
}
|
||||
|
||||
#else /* !FFCLOCK */
|
||||
|
||||
int
|
||||
sys_ffclock_getcounter(struct thread *td, struct ffclock_getcounter_args *uap)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
int
|
||||
sys_ffclock_setestimate(struct thread *td, struct ffclock_setestimate_args *uap)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
int
|
||||
sys_ffclock_getestimate(struct thread *td, struct ffclock_getestimate_args *uap)
|
||||
{
|
||||
|
||||
return (ENOSYS);
|
||||
}
|
||||
|
||||
#endif /* FFCLOCK */
|
||||
|
@ -154,6 +154,7 @@ s/\$//g
|
||||
printf "#include <sys/signal.h>\n" > sysarg
|
||||
printf "#include <sys/acl.h>\n" > sysarg
|
||||
printf "#include <sys/cpuset.h>\n" > sysarg
|
||||
printf "#include <sys/_ffcounter.h>\n" > sysarg
|
||||
printf "#include <sys/_semaphore.h>\n" > sysarg
|
||||
printf "#include <sys/ucontext.h>\n\n" > sysarg
|
||||
printf "#include <bsm/audit_kevents.h>\n\n" > sysarg
|
||||
|
@ -248,9 +248,9 @@ const char *syscallnames[] = {
|
||||
"ktimer_gettime", /* 238 = ktimer_gettime */
|
||||
"ktimer_getoverrun", /* 239 = ktimer_getoverrun */
|
||||
"nanosleep", /* 240 = nanosleep */
|
||||
"#241", /* 241 = nosys */
|
||||
"#242", /* 242 = nosys */
|
||||
"#243", /* 243 = nosys */
|
||||
"ffclock_getcounter", /* 241 = ffclock_getcounter */
|
||||
"ffclock_setestimate", /* 242 = ffclock_setestimate */
|
||||
"ffclock_getestimate", /* 243 = ffclock_getestimate */
|
||||
"#244", /* 244 = nosys */
|
||||
"#245", /* 245 = nosys */
|
||||
"#246", /* 246 = nosys */
|
||||
|
@ -456,9 +456,11 @@
|
||||
239 AUE_NULL STD { int ktimer_getoverrun(int timerid); }
|
||||
240 AUE_NULL STD { int nanosleep(const struct timespec *rqtp, \
|
||||
struct timespec *rmtp); }
|
||||
241 AUE_NULL UNIMPL nosys
|
||||
242 AUE_NULL UNIMPL nosys
|
||||
243 AUE_NULL UNIMPL nosys
|
||||
241 AUE_NULL STD { int ffclock_getcounter(ffcounter *ffcount); }
|
||||
242 AUE_NULL STD { int ffclock_setestimate( \
|
||||
struct ffclock_estimate *cest); }
|
||||
243 AUE_NULL STD { int ffclock_getestimate( \
|
||||
struct ffclock_estimate *cest); }
|
||||
244 AUE_NULL UNIMPL nosys
|
||||
245 AUE_NULL UNIMPL nosys
|
||||
246 AUE_NULL UNIMPL nosys
|
||||
|
@ -1337,6 +1337,27 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* ffclock_getcounter */
|
||||
case 241: {
|
||||
struct ffclock_getcounter_args *p = params;
|
||||
uarg[0] = (intptr_t) p->ffcount; /* ffcounter * */
|
||||
*n_args = 1;
|
||||
break;
|
||||
}
|
||||
/* ffclock_setestimate */
|
||||
case 242: {
|
||||
struct ffclock_setestimate_args *p = params;
|
||||
uarg[0] = (intptr_t) p->cest; /* struct ffclock_estimate * */
|
||||
*n_args = 1;
|
||||
break;
|
||||
}
|
||||
/* ffclock_getestimate */
|
||||
case 243: {
|
||||
struct ffclock_getestimate_args *p = params;
|
||||
uarg[0] = (intptr_t) p->cest; /* struct ffclock_estimate * */
|
||||
*n_args = 1;
|
||||
break;
|
||||
}
|
||||
/* ntp_gettime */
|
||||
case 248: {
|
||||
struct ntp_gettime_args *p = params;
|
||||
@ -5381,6 +5402,36 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* ffclock_getcounter */
|
||||
case 241:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "ffcounter *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* ffclock_setestimate */
|
||||
case 242:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "struct ffclock_estimate *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* ffclock_getestimate */
|
||||
case 243:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "struct ffclock_estimate *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* ntp_gettime */
|
||||
case 248:
|
||||
switch(ndx) {
|
||||
@ -9398,6 +9449,21 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* ffclock_getcounter */
|
||||
case 241:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* ffclock_setestimate */
|
||||
case 242:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* ffclock_getestimate */
|
||||
case 243:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* ntp_gettime */
|
||||
case 248:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
|
@ -216,6 +216,9 @@
|
||||
#define SYS_ktimer_gettime 238
|
||||
#define SYS_ktimer_getoverrun 239
|
||||
#define SYS_nanosleep 240
|
||||
#define SYS_ffclock_getcounter 241
|
||||
#define SYS_ffclock_setestimate 242
|
||||
#define SYS_ffclock_getestimate 243
|
||||
#define SYS_ntp_gettime 248
|
||||
#define SYS_minherit 250
|
||||
#define SYS_rfork 251
|
||||
|
@ -168,6 +168,9 @@ MIASM = \
|
||||
ktimer_gettime.o \
|
||||
ktimer_getoverrun.o \
|
||||
nanosleep.o \
|
||||
ffclock_getcounter.o \
|
||||
ffclock_setestimate.o \
|
||||
ffclock_getestimate.o \
|
||||
ntp_gettime.o \
|
||||
minherit.o \
|
||||
rfork.o \
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <sys/signal.h>
|
||||
#include <sys/acl.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/_ffcounter.h>
|
||||
#include <sys/_semaphore.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
@ -726,6 +727,15 @@ struct nanosleep_args {
|
||||
char rqtp_l_[PADL_(const struct timespec *)]; const struct timespec * rqtp; char rqtp_r_[PADR_(const struct timespec *)];
|
||||
char rmtp_l_[PADL_(struct timespec *)]; struct timespec * rmtp; char rmtp_r_[PADR_(struct timespec *)];
|
||||
};
|
||||
struct ffclock_getcounter_args {
|
||||
char ffcount_l_[PADL_(ffcounter *)]; ffcounter * ffcount; char ffcount_r_[PADR_(ffcounter *)];
|
||||
};
|
||||
struct ffclock_setestimate_args {
|
||||
char cest_l_[PADL_(struct ffclock_estimate *)]; struct ffclock_estimate * cest; char cest_r_[PADR_(struct ffclock_estimate *)];
|
||||
};
|
||||
struct ffclock_getestimate_args {
|
||||
char cest_l_[PADL_(struct ffclock_estimate *)]; struct ffclock_estimate * cest; char cest_r_[PADR_(struct ffclock_estimate *)];
|
||||
};
|
||||
struct ntp_gettime_args {
|
||||
char ntvp_l_[PADL_(struct ntptimeval *)]; struct ntptimeval * ntvp; char ntvp_r_[PADR_(struct ntptimeval *)];
|
||||
};
|
||||
@ -1894,6 +1904,9 @@ int sys_ktimer_settime(struct thread *, struct ktimer_settime_args *);
|
||||
int sys_ktimer_gettime(struct thread *, struct ktimer_gettime_args *);
|
||||
int sys_ktimer_getoverrun(struct thread *, struct ktimer_getoverrun_args *);
|
||||
int sys_nanosleep(struct thread *, struct nanosleep_args *);
|
||||
int sys_ffclock_getcounter(struct thread *, struct ffclock_getcounter_args *);
|
||||
int sys_ffclock_setestimate(struct thread *, struct ffclock_setestimate_args *);
|
||||
int sys_ffclock_getestimate(struct thread *, struct ffclock_getestimate_args *);
|
||||
int sys_ntp_gettime(struct thread *, struct ntp_gettime_args *);
|
||||
int sys_minherit(struct thread *, struct minherit_args *);
|
||||
int sys_rfork(struct thread *, struct rfork_args *);
|
||||
@ -2581,6 +2594,9 @@ int freebsd7_shmctl(struct thread *, struct freebsd7_shmctl_args *);
|
||||
#define SYS_AUE_ktimer_gettime AUE_NULL
|
||||
#define SYS_AUE_ktimer_getoverrun AUE_NULL
|
||||
#define SYS_AUE_nanosleep AUE_NULL
|
||||
#define SYS_AUE_ffclock_getcounter AUE_NULL
|
||||
#define SYS_AUE_ffclock_setestimate AUE_NULL
|
||||
#define SYS_AUE_ffclock_getestimate AUE_NULL
|
||||
#define SYS_AUE_ntp_gettime AUE_NULL
|
||||
#define SYS_AUE_minherit AUE_MINHERIT
|
||||
#define SYS_AUE_rfork AUE_RFORK
|
||||
|
@ -164,6 +164,15 @@ void ffclock_bindifftime(ffcounter ffdelta, struct bintime *bt);
|
||||
void ffclock_nanodifftime(ffcounter ffdelta, struct timespec *tsp);
|
||||
void ffclock_microdifftime(ffcounter ffdelta, struct timeval *tvp);
|
||||
|
||||
#else /* !_KERNEL */
|
||||
|
||||
/* Feed-Forward Clock system calls. */
|
||||
__BEGIN_DECLS
|
||||
int ffclock_getcounter(ffcounter *ffcount);
|
||||
int ffclock_getestimate(struct ffclock_estimate *cest);
|
||||
int ffclock_setestimate(struct ffclock_estimate *cest);
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif /* __BSD_VISIBLE */
|
||||
#endif /* _SYS_TIMEFF_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user