kern_ffclock.c revision 227986
1227745Slstewart/*- 2227745Slstewart * Copyright (c) 2011 The University of Melbourne 3227745Slstewart * All rights reserved. 4227745Slstewart * 5227745Slstewart * This software was developed by Julien Ridoux at the University of Melbourne 6227745Slstewart * under sponsorship from the FreeBSD Foundation. 7227745Slstewart * 8227745Slstewart * Redistribution and use in source and binary forms, with or without 9227745Slstewart * modification, are permitted provided that the following conditions 10227745Slstewart * are met: 11227745Slstewart * 1. Redistributions of source code must retain the above copyright 12227745Slstewart * notice, this list of conditions and the following disclaimer. 13227745Slstewart * 2. Redistributions in binary form must reproduce the above copyright 14227745Slstewart * notice, this list of conditions and the following disclaimer in the 15227745Slstewart * documentation and/or other materials provided with the distribution. 16227745Slstewart * 17227745Slstewart * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18227745Slstewart * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19227745Slstewart * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20227745Slstewart * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21227745Slstewart * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22227745Slstewart * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23227745Slstewart * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24227745Slstewart * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25227745Slstewart * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26227745Slstewart * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27227745Slstewart * SUCH DAMAGE. 28227745Slstewart */ 29227745Slstewart 30227745Slstewart#include <sys/cdefs.h> 31227745Slstewart__FBSDID("$FreeBSD: head/sys/kern/kern_ffclock.c 227986 2011-11-26 01:44:37Z lstewart $"); 32227745Slstewart 33227776Slstewart#include "opt_ffclock.h" 34227776Slstewart 35227745Slstewart#include <sys/param.h> 36227776Slstewart#include <sys/bus.h> 37227776Slstewart#include <sys/kernel.h> 38227776Slstewart#include <sys/lock.h> 39227776Slstewart#include <sys/module.h> 40227776Slstewart#include <sys/mutex.h> 41227776Slstewart#include <sys/priv.h> 42227776Slstewart#include <sys/proc.h> 43227747Slstewart#include <sys/sbuf.h> 44227776Slstewart#include <sys/sysent.h> 45227776Slstewart#include <sys/sysproto.h> 46227747Slstewart#include <sys/sysctl.h> 47227745Slstewart#include <sys/systm.h> 48227745Slstewart#include <sys/timeffc.h> 49227745Slstewart 50227776Slstewart#ifdef FFCLOCK 51227776Slstewart 52227986SlstewartFEATURE(ffclock, "Feed-forward clock support"); 53227986Slstewart 54227745Slstewartextern struct ffclock_estimate ffclock_estimate; 55227745Slstewartextern struct bintime ffclock_boottime; 56227776Slstewartextern int8_t ffclock_updated; 57227776Slstewartextern struct mtx ffclock_mtx; 58227745Slstewart 59227745Slstewart/* 60227745Slstewart * Feed-forward clock absolute time. This should be the preferred way to read 61227745Slstewart * the feed-forward clock for "wall-clock" type time. The flags allow to compose 62227745Slstewart * various flavours of absolute time (e.g. with or without leap seconds taken 63227745Slstewart * into account). If valid pointers are provided, the ffcounter value and an 64227745Slstewart * upper bound on clock error associated with the bintime are provided. 65227745Slstewart * NOTE: use ffclock_convert_abs() to differ the conversion of a ffcounter value 66227745Slstewart * read earlier. 67227745Slstewart */ 68227745Slstewartvoid 69227745Slstewartffclock_abstime(ffcounter *ffcount, struct bintime *bt, 70227745Slstewart struct bintime *error_bound, uint32_t flags) 71227745Slstewart{ 72227745Slstewart struct ffclock_estimate cest; 73227745Slstewart ffcounter ffc; 74227745Slstewart ffcounter update_ffcount; 75227745Slstewart ffcounter ffdelta_error; 76227745Slstewart 77227745Slstewart /* Get counter and corresponding time. */ 78227745Slstewart if ((flags & FFCLOCK_FAST) == FFCLOCK_FAST) 79227745Slstewart ffclock_last_tick(&ffc, bt, flags); 80227745Slstewart else { 81227745Slstewart ffclock_read_counter(&ffc); 82227745Slstewart ffclock_convert_abs(ffc, bt, flags); 83227745Slstewart } 84227745Slstewart 85227745Slstewart /* Current ffclock estimate, use update_ffcount as generation number. */ 86227745Slstewart do { 87227745Slstewart update_ffcount = ffclock_estimate.update_ffcount; 88227745Slstewart bcopy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate)); 89227745Slstewart } while (update_ffcount != ffclock_estimate.update_ffcount); 90227745Slstewart 91227745Slstewart /* 92227745Slstewart * Leap second adjustment. Total as seen by synchronisation algorithm 93227745Slstewart * since it started. cest.leapsec_next is the ffcounter prediction of 94227745Slstewart * when the next leapsecond occurs. 95227745Slstewart */ 96227745Slstewart if ((flags & FFCLOCK_LEAPSEC) == FFCLOCK_LEAPSEC) { 97227745Slstewart bt->sec -= cest.leapsec_total; 98227745Slstewart if (ffc > cest.leapsec_next) 99227745Slstewart bt->sec -= cest.leapsec; 100227745Slstewart } 101227745Slstewart 102227745Slstewart /* Boot time adjustment, for uptime/monotonic clocks. */ 103227745Slstewart if ((flags & FFCLOCK_UPTIME) == FFCLOCK_UPTIME) { 104227745Slstewart bintime_sub(bt, &ffclock_boottime); 105227745Slstewart } 106227745Slstewart 107227745Slstewart /* Compute error bound if a valid pointer has been passed. */ 108227745Slstewart if (error_bound) { 109227745Slstewart ffdelta_error = ffc - cest.update_ffcount; 110227745Slstewart ffclock_convert_diff(ffdelta_error, error_bound); 111227745Slstewart /* 18446744073709 = int(2^64/1e12), err_bound_rate in [ps/s] */ 112227745Slstewart bintime_mul(error_bound, cest.errb_rate * 113227745Slstewart (uint64_t)18446744073709LL); 114227745Slstewart /* 18446744073 = int(2^64 / 1e9), since err_abs in [ns] */ 115227745Slstewart bintime_addx(error_bound, cest.errb_abs * 116227745Slstewart (uint64_t)18446744073LL); 117227745Slstewart } 118227745Slstewart 119227745Slstewart if (ffcount) 120227745Slstewart *ffcount = ffc; 121227745Slstewart} 122227745Slstewart 123227745Slstewart/* 124227745Slstewart * Feed-forward difference clock. This should be the preferred way to convert a 125227745Slstewart * time interval in ffcounter values into a time interval in seconds. If a valid 126227745Slstewart * pointer is passed, an upper bound on the error in computing the time interval 127227745Slstewart * in seconds is provided. 128227745Slstewart */ 129227745Slstewartvoid 130227745Slstewartffclock_difftime(ffcounter ffdelta, struct bintime *bt, 131227745Slstewart struct bintime *error_bound) 132227745Slstewart{ 133227745Slstewart ffcounter update_ffcount; 134227745Slstewart uint32_t err_rate; 135227745Slstewart 136227745Slstewart ffclock_convert_diff(ffdelta, bt); 137227745Slstewart 138227745Slstewart if (error_bound) { 139227745Slstewart do { 140227745Slstewart update_ffcount = ffclock_estimate.update_ffcount; 141227745Slstewart err_rate = ffclock_estimate.errb_rate; 142227745Slstewart } while (update_ffcount != ffclock_estimate.update_ffcount); 143227745Slstewart 144227745Slstewart ffclock_convert_diff(ffdelta, error_bound); 145227745Slstewart /* 18446744073709 = int(2^64/1e12), err_bound_rate in [ps/s] */ 146227745Slstewart bintime_mul(error_bound, err_rate * (uint64_t)18446744073709LL); 147227745Slstewart } 148227745Slstewart} 149227747Slstewart 150227747Slstewart/* 151227747Slstewart * Sysctl for the Feed-Forward Clock. 152227747Slstewart */ 153227747Slstewart 154227747Slstewartstatic int ffclock_version = 2; 155227747SlstewartSYSCTL_NODE(_kern, OID_AUTO, ffclock, CTLFLAG_RW, 0, 156227747Slstewart "Feed-Forward Clock Support"); 157227747SlstewartSYSCTL_INT(_kern_ffclock, OID_AUTO, version, CTLFLAG_RD, &ffclock_version, 0, 158227747Slstewart "Version of Feed-Forward Clock Support"); 159227747Slstewart 160227747Slstewart/* 161227747Slstewart * Sysctl to select which clock is read when calling any of the 162227747Slstewart * [get]{bin,nano,micro}[up]time() functions. 163227747Slstewart */ 164227747Slstewartchar *sysclocks[] = {"feedback", "feed-forward"}; 165227747Slstewart 166227747Slstewart#define NUM_SYSCLOCKS (sizeof(sysclocks) / sizeof(*sysclocks)) 167227747Slstewart 168227747Slstewart/* Report or change the active timecounter hardware. */ 169227747Slstewartstatic int 170227747Slstewartsysctl_kern_ffclock_choice(SYSCTL_HANDLER_ARGS) 171227747Slstewart{ 172227747Slstewart struct sbuf *s; 173227747Slstewart int clk, error; 174227747Slstewart 175227747Slstewart s = sbuf_new_for_sysctl(NULL, NULL, 16 * NUM_SYSCLOCKS, req); 176227747Slstewart if (s == NULL) 177227747Slstewart return (ENOMEM); 178227747Slstewart 179227747Slstewart for (clk = 0; clk < NUM_SYSCLOCKS; clk++) { 180227747Slstewart sbuf_cat(s, sysclocks[clk]); 181227747Slstewart if (clk + 1 < NUM_SYSCLOCKS) 182227747Slstewart sbuf_cat(s, " "); 183227747Slstewart } 184227747Slstewart error = sbuf_finish(s); 185227747Slstewart sbuf_delete(s); 186227747Slstewart 187227747Slstewart return (error); 188227747Slstewart} 189227747Slstewart 190227747SlstewartSYSCTL_PROC(_kern_ffclock, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD, 191227747Slstewart 0, 0, sysctl_kern_ffclock_choice, "A", "Clock paradigms available"); 192227747Slstewart 193227747Slstewartextern int sysclock_active; 194227747Slstewart 195227747Slstewartstatic int 196227747Slstewartsysctl_kern_ffclock_active(SYSCTL_HANDLER_ARGS) 197227747Slstewart{ 198227747Slstewart char newclock[32]; 199227747Slstewart int error; 200227747Slstewart 201227747Slstewart switch (sysclock_active) { 202227747Slstewart case SYSCLOCK_FBCK: 203227747Slstewart strlcpy(newclock, sysclocks[SYSCLOCK_FBCK], sizeof(newclock)); 204227747Slstewart break; 205227747Slstewart case SYSCLOCK_FFWD: 206227747Slstewart strlcpy(newclock, sysclocks[SYSCLOCK_FFWD], sizeof(newclock)); 207227747Slstewart break; 208227747Slstewart } 209227747Slstewart 210227747Slstewart error = sysctl_handle_string(oidp, &newclock[0], sizeof(newclock), req); 211227747Slstewart if (error != 0 || req->newptr == NULL) 212227747Slstewart return (error); 213227747Slstewart if (strncmp(newclock, sysclocks[SYSCLOCK_FBCK], 214227747Slstewart sizeof(sysclocks[SYSCLOCK_FBCK])) == 0) 215227747Slstewart sysclock_active = SYSCLOCK_FBCK; 216227747Slstewart else if (strncmp(newclock, sysclocks[SYSCLOCK_FFWD], 217227747Slstewart sizeof(sysclocks[SYSCLOCK_FFWD])) == 0) 218227747Slstewart sysclock_active = SYSCLOCK_FFWD; 219227747Slstewart else 220227747Slstewart return (EINVAL); 221227747Slstewart 222227747Slstewart return (error); 223227747Slstewart} 224227747Slstewart 225227747SlstewartSYSCTL_PROC(_kern_ffclock, OID_AUTO, active, CTLTYPE_STRING | CTLFLAG_RW, 226227747Slstewart 0, 0, sysctl_kern_ffclock_active, "A", "Kernel clock selected"); 227227747Slstewart 228227776Slstewartint sysctl_kern_ffclock_ffcounter_bypass = 0; 229227776Slstewart 230227776SlstewartSYSCTL_INT(_kern_ffclock, OID_AUTO, ffcounter_bypass, CTLFLAG_RW, 231227776Slstewart &sysctl_kern_ffclock_ffcounter_bypass, 0, 232227776Slstewart "Use reliable hardware timecounter as the Feed-Forward Counter"); 233227776Slstewart 234227747Slstewart/* 235227747Slstewart * High level functions to access the Feed-Forward Clock. 236227747Slstewart */ 237227747Slstewartvoid 238227747Slstewartffclock_bintime(struct bintime *bt) 239227747Slstewart{ 240227747Slstewart 241227747Slstewart ffclock_abstime(NULL, bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC); 242227747Slstewart} 243227747Slstewart 244227747Slstewartvoid 245227747Slstewartffclock_nanotime(struct timespec *tsp) 246227747Slstewart{ 247227747Slstewart struct bintime bt; 248227747Slstewart 249227747Slstewart ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC); 250227747Slstewart bintime2timespec(&bt, tsp); 251227747Slstewart} 252227747Slstewart 253227747Slstewartvoid 254227747Slstewartffclock_microtime(struct timeval *tvp) 255227747Slstewart{ 256227747Slstewart struct bintime bt; 257227747Slstewart 258227747Slstewart ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC); 259227747Slstewart bintime2timeval(&bt, tvp); 260227747Slstewart} 261227747Slstewart 262227747Slstewartvoid 263227747Slstewartffclock_getbintime(struct bintime *bt) 264227747Slstewart{ 265227747Slstewart 266227747Slstewart ffclock_abstime(NULL, bt, NULL, 267227747Slstewart FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST); 268227747Slstewart} 269227747Slstewart 270227747Slstewartvoid 271227747Slstewartffclock_getnanotime(struct timespec *tsp) 272227747Slstewart{ 273227747Slstewart struct bintime bt; 274227747Slstewart 275227747Slstewart ffclock_abstime(NULL, &bt, NULL, 276227747Slstewart FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST); 277227747Slstewart bintime2timespec(&bt, tsp); 278227747Slstewart} 279227747Slstewart 280227747Slstewartvoid 281227747Slstewartffclock_getmicrotime(struct timeval *tvp) 282227747Slstewart{ 283227747Slstewart struct bintime bt; 284227747Slstewart 285227747Slstewart ffclock_abstime(NULL, &bt, NULL, 286227747Slstewart FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST); 287227747Slstewart bintime2timeval(&bt, tvp); 288227747Slstewart} 289227747Slstewart 290227747Slstewartvoid 291227747Slstewartffclock_binuptime(struct bintime *bt) 292227747Slstewart{ 293227747Slstewart 294227747Slstewart ffclock_abstime(NULL, bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME); 295227747Slstewart} 296227747Slstewart 297227747Slstewartvoid 298227747Slstewartffclock_nanouptime(struct timespec *tsp) 299227747Slstewart{ 300227747Slstewart struct bintime bt; 301227747Slstewart 302227747Slstewart ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME); 303227747Slstewart bintime2timespec(&bt, tsp); 304227747Slstewart} 305227747Slstewart 306227747Slstewartvoid 307227747Slstewartffclock_microuptime(struct timeval *tvp) 308227747Slstewart{ 309227747Slstewart struct bintime bt; 310227747Slstewart 311227747Slstewart ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME); 312227747Slstewart bintime2timeval(&bt, tvp); 313227747Slstewart} 314227747Slstewart 315227747Slstewartvoid 316227747Slstewartffclock_getbinuptime(struct bintime *bt) 317227747Slstewart{ 318227747Slstewart 319227747Slstewart ffclock_abstime(NULL, bt, NULL, 320227747Slstewart FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST); 321227747Slstewart} 322227747Slstewart 323227747Slstewartvoid 324227747Slstewartffclock_getnanouptime(struct timespec *tsp) 325227747Slstewart{ 326227747Slstewart struct bintime bt; 327227747Slstewart 328227747Slstewart ffclock_abstime(NULL, &bt, NULL, 329227747Slstewart FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST); 330227747Slstewart bintime2timespec(&bt, tsp); 331227747Slstewart} 332227747Slstewart 333227747Slstewartvoid 334227747Slstewartffclock_getmicrouptime(struct timeval *tvp) 335227747Slstewart{ 336227747Slstewart struct bintime bt; 337227747Slstewart 338227747Slstewart ffclock_abstime(NULL, &bt, NULL, 339227747Slstewart FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST); 340227747Slstewart bintime2timeval(&bt, tvp); 341227747Slstewart} 342227747Slstewart 343227747Slstewartvoid 344227747Slstewartffclock_bindifftime(ffcounter ffdelta, struct bintime *bt) 345227747Slstewart{ 346227747Slstewart 347227747Slstewart ffclock_difftime(ffdelta, bt, NULL); 348227747Slstewart} 349227747Slstewart 350227747Slstewartvoid 351227747Slstewartffclock_nanodifftime(ffcounter ffdelta, struct timespec *tsp) 352227747Slstewart{ 353227747Slstewart struct bintime bt; 354227747Slstewart 355227747Slstewart ffclock_difftime(ffdelta, &bt, NULL); 356227747Slstewart bintime2timespec(&bt, tsp); 357227747Slstewart} 358227747Slstewart 359227747Slstewartvoid 360227747Slstewartffclock_microdifftime(ffcounter ffdelta, struct timeval *tvp) 361227747Slstewart{ 362227747Slstewart struct bintime bt; 363227747Slstewart 364227747Slstewart ffclock_difftime(ffdelta, &bt, NULL); 365227747Slstewart bintime2timeval(&bt, tvp); 366227747Slstewart} 367227776Slstewart 368227776Slstewart/* 369227776Slstewart * System call allowing userland applications to retrieve the current value of 370227776Slstewart * the Feed-Forward Clock counter. 371227776Slstewart */ 372227776Slstewart#ifndef _SYS_SYSPROTO_H_ 373227776Slstewartstruct ffclock_getcounter_args { 374227776Slstewart ffcounter *ffcount; 375227776Slstewart}; 376227776Slstewart#endif 377227776Slstewart/* ARGSUSED */ 378227776Slstewartint 379227776Slstewartsys_ffclock_getcounter(struct thread *td, struct ffclock_getcounter_args *uap) 380227776Slstewart{ 381227776Slstewart ffcounter ffcount; 382227776Slstewart int error; 383227776Slstewart 384227776Slstewart ffcount = 0; 385227776Slstewart ffclock_read_counter(&ffcount); 386227776Slstewart if (ffcount == 0) 387227776Slstewart return (EAGAIN); 388227776Slstewart error = copyout(&ffcount, uap->ffcount, sizeof(ffcounter)); 389227776Slstewart 390227776Slstewart return (error); 391227776Slstewart} 392227776Slstewart 393227776Slstewart/* 394227776Slstewart * System call allowing the synchronisation daemon to push new feed-foward clock 395227776Slstewart * estimates to the kernel. Acquire ffclock_mtx to prevent concurrent updates 396227776Slstewart * and ensure data consistency. 397227776Slstewart * NOTE: ffclock_updated signals the fftimehands that new estimates are 398227776Slstewart * available. The updated estimates are picked up by the fftimehands on next 399227776Slstewart * tick, which could take as long as 1/hz seconds (if ticks are not missed). 400227776Slstewart */ 401227776Slstewart#ifndef _SYS_SYSPROTO_H_ 402227776Slstewartstruct ffclock_setestimate_args { 403227776Slstewart struct ffclock_estimate *cest; 404227776Slstewart}; 405227776Slstewart#endif 406227776Slstewart/* ARGSUSED */ 407227776Slstewartint 408227776Slstewartsys_ffclock_setestimate(struct thread *td, struct ffclock_setestimate_args *uap) 409227776Slstewart{ 410227776Slstewart struct ffclock_estimate cest; 411227776Slstewart int error; 412227776Slstewart 413227776Slstewart /* Reuse of PRIV_CLOCK_SETTIME. */ 414227776Slstewart if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0) 415227776Slstewart return (error); 416227776Slstewart 417227776Slstewart if ((error = copyin(uap->cest, &cest, sizeof(struct ffclock_estimate))) 418227776Slstewart != 0) 419227776Slstewart return (error); 420227776Slstewart 421227776Slstewart mtx_lock(&ffclock_mtx); 422227776Slstewart memcpy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate)); 423227776Slstewart ffclock_updated++; 424227776Slstewart mtx_unlock(&ffclock_mtx); 425227776Slstewart return (error); 426227776Slstewart} 427227776Slstewart 428227776Slstewart/* 429227776Slstewart * System call allowing userland applications to retrieve the clock estimates 430227776Slstewart * stored within the kernel. It is useful to kickstart the synchronisation 431227776Slstewart * daemon with the kernel's knowledge of hardware timecounter. 432227776Slstewart */ 433227776Slstewart#ifndef _SYS_SYSPROTO_H_ 434227776Slstewartstruct ffclock_getestimate_args { 435227776Slstewart struct ffclock_estimate *cest; 436227776Slstewart}; 437227776Slstewart#endif 438227776Slstewart/* ARGSUSED */ 439227776Slstewartint 440227776Slstewartsys_ffclock_getestimate(struct thread *td, struct ffclock_getestimate_args *uap) 441227776Slstewart{ 442227776Slstewart struct ffclock_estimate cest; 443227776Slstewart int error; 444227776Slstewart 445227776Slstewart mtx_lock(&ffclock_mtx); 446227776Slstewart memcpy(&cest, &ffclock_estimate, sizeof(struct ffclock_estimate)); 447227776Slstewart mtx_unlock(&ffclock_mtx); 448227776Slstewart error = copyout(&cest, uap->cest, sizeof(struct ffclock_estimate)); 449227776Slstewart return (error); 450227776Slstewart} 451227776Slstewart 452227776Slstewart#else /* !FFCLOCK */ 453227776Slstewart 454227776Slstewartint 455227776Slstewartsys_ffclock_getcounter(struct thread *td, struct ffclock_getcounter_args *uap) 456227776Slstewart{ 457227776Slstewart 458227776Slstewart return (ENOSYS); 459227776Slstewart} 460227776Slstewart 461227776Slstewartint 462227776Slstewartsys_ffclock_setestimate(struct thread *td, struct ffclock_setestimate_args *uap) 463227776Slstewart{ 464227776Slstewart 465227776Slstewart return (ENOSYS); 466227776Slstewart} 467227776Slstewart 468227776Slstewartint 469227776Slstewartsys_ffclock_getestimate(struct thread *td, struct ffclock_getestimate_args *uap) 470227776Slstewart{ 471227776Slstewart 472227776Slstewart return (ENOSYS); 473227776Slstewart} 474227776Slstewart 475227776Slstewart#endif /* FFCLOCK */ 476