diff options
-rw-r--r-- | lib/libc/sys/Makefile.inc | 4 | ||||
-rw-r--r-- | lib/libc/sys/Symbol.map | 3 | ||||
-rw-r--r-- | lib/libc/sys/ffclock.2 | 177 | ||||
-rw-r--r-- | sys/amd64/linux32/linux32_proto.h | 1 | ||||
-rw-r--r-- | sys/compat/freebsd32/freebsd32_proto.h | 1 | ||||
-rw-r--r-- | sys/compat/freebsd32/freebsd32_syscall.h | 3 | ||||
-rw-r--r-- | sys/compat/freebsd32/freebsd32_syscalls.c | 6 | ||||
-rw-r--r-- | sys/compat/freebsd32/freebsd32_sysent.c | 6 | ||||
-rw-r--r-- | sys/compat/freebsd32/freebsd32_systrace_args.c | 66 | ||||
-rw-r--r-- | sys/compat/freebsd32/syscalls.master | 8 | ||||
-rw-r--r-- | sys/conf/files | 2 | ||||
-rw-r--r-- | sys/i386/linux/linux_proto.h | 1 | ||||
-rw-r--r-- | sys/kern/init_sysent.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_ffclock.c | 130 | ||||
-rw-r--r-- | sys/kern/makesyscalls.sh | 1 | ||||
-rw-r--r-- | sys/kern/syscalls.c | 6 | ||||
-rw-r--r-- | sys/kern/syscalls.master | 8 | ||||
-rw-r--r-- | sys/kern/systrace_args.c | 66 | ||||
-rw-r--r-- | sys/sys/syscall.h | 3 | ||||
-rw-r--r-- | sys/sys/syscall.mk | 3 | ||||
-rw-r--r-- | sys/sys/sysproto.h | 16 | ||||
-rw-r--r-- | sys/sys/timeffc.h | 9 |
22 files changed, 506 insertions, 20 deletions
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index 6da6a00..ea38b51 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -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 diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index d0c0c94..f1c1567 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -365,6 +365,9 @@ FBSD_1.2 { cap_getmode; cap_new; cap_getrights; + ffclock_getcounter; + ffclock_getestimate; + ffclock_setestimate; getloginclass; pdfork; pdgetpid; diff --git a/lib/libc/sys/ffclock.2 b/lib/libc/sys/ffclock.2 new file mode 100644 index 0000000..0e8f09b --- /dev/null +++ b/lib/libc/sys/ffclock.2 @@ -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. diff --git a/sys/amd64/linux32/linux32_proto.h b/sys/amd64/linux32/linux32_proto.h index 94d6c79..cc9b97d 100644 --- a/sys/amd64/linux32/linux32_proto.h +++ b/sys/amd64/linux32/linux32_proto.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> diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h index 644f8f3..1d6310b 100644 --- a/sys/compat/freebsd32/freebsd32_proto.h +++ b/sys/compat/freebsd32/freebsd32_proto.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> diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h index 108af4d..d21b583 100644 --- a/sys/compat/freebsd32/freebsd32_syscall.h +++ b/sys/compat/freebsd32/freebsd32_syscall.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 diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c index b363f01..c58a414 100644 --- a/sys/compat/freebsd32/freebsd32_syscalls.c +++ b/sys/compat/freebsd32/freebsd32_syscalls.c @@ -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 */ diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c index ff6f4d4..4371d16 100644 --- a/sys/compat/freebsd32/freebsd32_sysent.c +++ b/sys/compat/freebsd32/freebsd32_sysent.c @@ -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 */ diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c index b529c33..7f6bf68 100644 --- a/sys/compat/freebsd32/freebsd32_systrace_args.c +++ b/sys/compat/freebsd32/freebsd32_systrace_args.c @@ -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) diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 78598c3..b80fd9c 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -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 diff --git a/sys/conf/files b/sys/conf/files index 1ed2c20..4d98f28 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -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 diff --git a/sys/i386/linux/linux_proto.h b/sys/i386/linux/linux_proto.h index c3bac4d..d480012 100644 --- a/sys/i386/linux/linux_proto.h +++ b/sys/i386/linux/linux_proto.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> diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index ad0b224..7ace326 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -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 */ diff --git a/sys/kern/kern_ffclock.c b/sys/kern/kern_ffclock.c index 4d31c40..62b91f4 100644 --- a/sys/kern/kern_ffclock.c +++ b/sys/kern/kern_ffclock.c @@ -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 */ diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh index 1f081ce..21e6046 100644 --- a/sys/kern/makesyscalls.sh +++ b/sys/kern/makesyscalls.sh @@ -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 diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 846f232..dd82db7 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -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 */ diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 3773289..e10af89 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -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 diff --git a/sys/kern/systrace_args.c b/sys/kern/systrace_args.c index 0933685..4a5d72a 100644 --- a/sys/kern/systrace_args.c +++ b/sys/kern/systrace_args.c @@ -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) diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index e8e213f..a9a1fb2 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -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 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 6a17b71..1113886 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -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 \ diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index cf4eaec..84a0ed7 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.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> @@ -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 diff --git a/sys/sys/timeffc.h b/sys/sys/timeffc.h index c2a04ab..0c58c05 100644 --- a/sys/sys/timeffc.h +++ b/sys/sys/timeffc.h @@ -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_ */ |