xref: /freebsd/sys/kern/kern_ffclock.c (revision 9bce0f05fe210ecba3befd4fb110bf4520a1e490)
1f464c5ccSLawrence Stewart /*-
2f464c5ccSLawrence Stewart  * Copyright (c) 2011 The University of Melbourne
3f464c5ccSLawrence Stewart  * All rights reserved.
4f464c5ccSLawrence Stewart  *
5f464c5ccSLawrence Stewart  * This software was developed by Julien Ridoux at the University of Melbourne
6f464c5ccSLawrence Stewart  * under sponsorship from the FreeBSD Foundation.
7f464c5ccSLawrence Stewart  *
8f464c5ccSLawrence Stewart  * Redistribution and use in source and binary forms, with or without
9f464c5ccSLawrence Stewart  * modification, are permitted provided that the following conditions
10f464c5ccSLawrence Stewart  * are met:
11f464c5ccSLawrence Stewart  * 1. Redistributions of source code must retain the above copyright
12f464c5ccSLawrence Stewart  *    notice, this list of conditions and the following disclaimer.
13f464c5ccSLawrence Stewart  * 2. Redistributions in binary form must reproduce the above copyright
14f464c5ccSLawrence Stewart  *    notice, this list of conditions and the following disclaimer in the
15f464c5ccSLawrence Stewart  *    documentation and/or other materials provided with the distribution.
16f464c5ccSLawrence Stewart  *
17f464c5ccSLawrence Stewart  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18f464c5ccSLawrence Stewart  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19f464c5ccSLawrence Stewart  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20f464c5ccSLawrence Stewart  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21f464c5ccSLawrence Stewart  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22f464c5ccSLawrence Stewart  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23f464c5ccSLawrence Stewart  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24f464c5ccSLawrence Stewart  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25f464c5ccSLawrence Stewart  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26f464c5ccSLawrence Stewart  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27f464c5ccSLawrence Stewart  * SUCH DAMAGE.
28f464c5ccSLawrence Stewart  */
29f464c5ccSLawrence Stewart 
30f464c5ccSLawrence Stewart #include <sys/cdefs.h>
31f464c5ccSLawrence Stewart __FBSDID("$FreeBSD$");
32f464c5ccSLawrence Stewart 
33f464c5ccSLawrence Stewart #include <sys/param.h>
34*9bce0f05SLawrence Stewart #include <sys/sbuf.h>
35*9bce0f05SLawrence Stewart #include <sys/sysctl.h>
36f464c5ccSLawrence Stewart #include <sys/systm.h>
37f464c5ccSLawrence Stewart #include <sys/timeffc.h>
38f464c5ccSLawrence Stewart 
39f464c5ccSLawrence Stewart extern struct ffclock_estimate ffclock_estimate;
40f464c5ccSLawrence Stewart extern struct bintime ffclock_boottime;
41f464c5ccSLawrence Stewart 
42f464c5ccSLawrence Stewart /*
43f464c5ccSLawrence Stewart  * Feed-forward clock absolute time. This should be the preferred way to read
44f464c5ccSLawrence Stewart  * the feed-forward clock for "wall-clock" type time. The flags allow to compose
45f464c5ccSLawrence Stewart  * various flavours of absolute time (e.g. with or without leap seconds taken
46f464c5ccSLawrence Stewart  * into account). If valid pointers are provided, the ffcounter value and an
47f464c5ccSLawrence Stewart  * upper bound on clock error associated with the bintime are provided.
48f464c5ccSLawrence Stewart  * NOTE: use ffclock_convert_abs() to differ the conversion of a ffcounter value
49f464c5ccSLawrence Stewart  * read earlier.
50f464c5ccSLawrence Stewart  */
51f464c5ccSLawrence Stewart void
52f464c5ccSLawrence Stewart ffclock_abstime(ffcounter *ffcount, struct bintime *bt,
53f464c5ccSLawrence Stewart     struct bintime *error_bound, uint32_t flags)
54f464c5ccSLawrence Stewart {
55f464c5ccSLawrence Stewart 	struct ffclock_estimate cest;
56f464c5ccSLawrence Stewart 	ffcounter ffc;
57f464c5ccSLawrence Stewart 	ffcounter update_ffcount;
58f464c5ccSLawrence Stewart 	ffcounter ffdelta_error;
59f464c5ccSLawrence Stewart 
60f464c5ccSLawrence Stewart 	/* Get counter and corresponding time. */
61f464c5ccSLawrence Stewart 	if ((flags & FFCLOCK_FAST) == FFCLOCK_FAST)
62f464c5ccSLawrence Stewart 		ffclock_last_tick(&ffc, bt, flags);
63f464c5ccSLawrence Stewart 	else {
64f464c5ccSLawrence Stewart 		ffclock_read_counter(&ffc);
65f464c5ccSLawrence Stewart 		ffclock_convert_abs(ffc, bt, flags);
66f464c5ccSLawrence Stewart 	}
67f464c5ccSLawrence Stewart 
68f464c5ccSLawrence Stewart 	/* Current ffclock estimate, use update_ffcount as generation number. */
69f464c5ccSLawrence Stewart 	do {
70f464c5ccSLawrence Stewart 		update_ffcount = ffclock_estimate.update_ffcount;
71f464c5ccSLawrence Stewart 		bcopy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate));
72f464c5ccSLawrence Stewart 	} while (update_ffcount != ffclock_estimate.update_ffcount);
73f464c5ccSLawrence Stewart 
74f464c5ccSLawrence Stewart 	/*
75f464c5ccSLawrence Stewart 	 * Leap second adjustment. Total as seen by synchronisation algorithm
76f464c5ccSLawrence Stewart 	 * since it started. cest.leapsec_next is the ffcounter prediction of
77f464c5ccSLawrence Stewart 	 * when the next leapsecond occurs.
78f464c5ccSLawrence Stewart 	 */
79f464c5ccSLawrence Stewart 	if ((flags & FFCLOCK_LEAPSEC) == FFCLOCK_LEAPSEC) {
80f464c5ccSLawrence Stewart 		bt->sec -= cest.leapsec_total;
81f464c5ccSLawrence Stewart 		if (ffc > cest.leapsec_next)
82f464c5ccSLawrence Stewart 			bt->sec -= cest.leapsec;
83f464c5ccSLawrence Stewart 	}
84f464c5ccSLawrence Stewart 
85f464c5ccSLawrence Stewart 	/* Boot time adjustment, for uptime/monotonic clocks. */
86f464c5ccSLawrence Stewart 	if ((flags & FFCLOCK_UPTIME) == FFCLOCK_UPTIME) {
87f464c5ccSLawrence Stewart 		bintime_sub(bt, &ffclock_boottime);
88f464c5ccSLawrence Stewart 	}
89f464c5ccSLawrence Stewart 
90f464c5ccSLawrence Stewart 	/* Compute error bound if a valid pointer has been passed. */
91f464c5ccSLawrence Stewart 	if (error_bound) {
92f464c5ccSLawrence Stewart 		ffdelta_error = ffc - cest.update_ffcount;
93f464c5ccSLawrence Stewart 		ffclock_convert_diff(ffdelta_error, error_bound);
94f464c5ccSLawrence Stewart 		/* 18446744073709 = int(2^64/1e12), err_bound_rate in [ps/s] */
95f464c5ccSLawrence Stewart 		bintime_mul(error_bound, cest.errb_rate *
96f464c5ccSLawrence Stewart 		    (uint64_t)18446744073709LL);
97f464c5ccSLawrence Stewart 		/* 18446744073 = int(2^64 / 1e9), since err_abs in [ns] */
98f464c5ccSLawrence Stewart 		bintime_addx(error_bound, cest.errb_abs *
99f464c5ccSLawrence Stewart 		    (uint64_t)18446744073LL);
100f464c5ccSLawrence Stewart 	}
101f464c5ccSLawrence Stewart 
102f464c5ccSLawrence Stewart 	if (ffcount)
103f464c5ccSLawrence Stewart 		*ffcount = ffc;
104f464c5ccSLawrence Stewart }
105f464c5ccSLawrence Stewart 
106f464c5ccSLawrence Stewart /*
107f464c5ccSLawrence Stewart  * Feed-forward difference clock. This should be the preferred way to convert a
108f464c5ccSLawrence Stewart  * time interval in ffcounter values into a time interval in seconds. If a valid
109f464c5ccSLawrence Stewart  * pointer is passed, an upper bound on the error in computing the time interval
110f464c5ccSLawrence Stewart  * in seconds is provided.
111f464c5ccSLawrence Stewart  */
112f464c5ccSLawrence Stewart void
113f464c5ccSLawrence Stewart ffclock_difftime(ffcounter ffdelta, struct bintime *bt,
114f464c5ccSLawrence Stewart     struct bintime *error_bound)
115f464c5ccSLawrence Stewart {
116f464c5ccSLawrence Stewart 	ffcounter update_ffcount;
117f464c5ccSLawrence Stewart 	uint32_t err_rate;
118f464c5ccSLawrence Stewart 
119f464c5ccSLawrence Stewart 	ffclock_convert_diff(ffdelta, bt);
120f464c5ccSLawrence Stewart 
121f464c5ccSLawrence Stewart 	if (error_bound) {
122f464c5ccSLawrence Stewart 		do {
123f464c5ccSLawrence Stewart 			update_ffcount = ffclock_estimate.update_ffcount;
124f464c5ccSLawrence Stewart 			err_rate = ffclock_estimate.errb_rate;
125f464c5ccSLawrence Stewart 		} while (update_ffcount != ffclock_estimate.update_ffcount);
126f464c5ccSLawrence Stewart 
127f464c5ccSLawrence Stewart 		ffclock_convert_diff(ffdelta, error_bound);
128f464c5ccSLawrence Stewart 		/* 18446744073709 = int(2^64/1e12), err_bound_rate in [ps/s] */
129f464c5ccSLawrence Stewart 		bintime_mul(error_bound, err_rate * (uint64_t)18446744073709LL);
130f464c5ccSLawrence Stewart 	}
131f464c5ccSLawrence Stewart }
132*9bce0f05SLawrence Stewart 
133*9bce0f05SLawrence Stewart /*
134*9bce0f05SLawrence Stewart  * Sysctl for the Feed-Forward Clock.
135*9bce0f05SLawrence Stewart  */
136*9bce0f05SLawrence Stewart 
137*9bce0f05SLawrence Stewart static int ffclock_version = 2;
138*9bce0f05SLawrence Stewart SYSCTL_NODE(_kern, OID_AUTO, ffclock, CTLFLAG_RW, 0,
139*9bce0f05SLawrence Stewart     "Feed-Forward Clock Support");
140*9bce0f05SLawrence Stewart SYSCTL_INT(_kern_ffclock, OID_AUTO, version, CTLFLAG_RD, &ffclock_version, 0,
141*9bce0f05SLawrence Stewart     "Version of Feed-Forward Clock Support");
142*9bce0f05SLawrence Stewart 
143*9bce0f05SLawrence Stewart /*
144*9bce0f05SLawrence Stewart  * Sysctl to select which clock is read when calling any of the
145*9bce0f05SLawrence Stewart  * [get]{bin,nano,micro}[up]time() functions.
146*9bce0f05SLawrence Stewart  */
147*9bce0f05SLawrence Stewart char *sysclocks[] = {"feedback", "feed-forward"};
148*9bce0f05SLawrence Stewart 
149*9bce0f05SLawrence Stewart #define	NUM_SYSCLOCKS (sizeof(sysclocks) / sizeof(*sysclocks))
150*9bce0f05SLawrence Stewart 
151*9bce0f05SLawrence Stewart /* Report or change the active timecounter hardware. */
152*9bce0f05SLawrence Stewart static int
153*9bce0f05SLawrence Stewart sysctl_kern_ffclock_choice(SYSCTL_HANDLER_ARGS)
154*9bce0f05SLawrence Stewart {
155*9bce0f05SLawrence Stewart 	struct sbuf *s;
156*9bce0f05SLawrence Stewart 	int clk, error;
157*9bce0f05SLawrence Stewart 
158*9bce0f05SLawrence Stewart 	s = sbuf_new_for_sysctl(NULL, NULL, 16 * NUM_SYSCLOCKS, req);
159*9bce0f05SLawrence Stewart 	if (s == NULL)
160*9bce0f05SLawrence Stewart 		return (ENOMEM);
161*9bce0f05SLawrence Stewart 
162*9bce0f05SLawrence Stewart 	for (clk = 0; clk < NUM_SYSCLOCKS; clk++) {
163*9bce0f05SLawrence Stewart 		sbuf_cat(s, sysclocks[clk]);
164*9bce0f05SLawrence Stewart 		if (clk + 1 < NUM_SYSCLOCKS)
165*9bce0f05SLawrence Stewart 			sbuf_cat(s, " ");
166*9bce0f05SLawrence Stewart 	}
167*9bce0f05SLawrence Stewart 	error = sbuf_finish(s);
168*9bce0f05SLawrence Stewart 	sbuf_delete(s);
169*9bce0f05SLawrence Stewart 
170*9bce0f05SLawrence Stewart 	return (error);
171*9bce0f05SLawrence Stewart }
172*9bce0f05SLawrence Stewart 
173*9bce0f05SLawrence Stewart SYSCTL_PROC(_kern_ffclock, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD,
174*9bce0f05SLawrence Stewart     0, 0, sysctl_kern_ffclock_choice, "A", "Clock paradigms available");
175*9bce0f05SLawrence Stewart 
176*9bce0f05SLawrence Stewart extern int sysclock_active;
177*9bce0f05SLawrence Stewart 
178*9bce0f05SLawrence Stewart static int
179*9bce0f05SLawrence Stewart sysctl_kern_ffclock_active(SYSCTL_HANDLER_ARGS)
180*9bce0f05SLawrence Stewart {
181*9bce0f05SLawrence Stewart 	char newclock[32];
182*9bce0f05SLawrence Stewart 	int error;
183*9bce0f05SLawrence Stewart 
184*9bce0f05SLawrence Stewart 	switch (sysclock_active) {
185*9bce0f05SLawrence Stewart 	case SYSCLOCK_FBCK:
186*9bce0f05SLawrence Stewart 		strlcpy(newclock, sysclocks[SYSCLOCK_FBCK], sizeof(newclock));
187*9bce0f05SLawrence Stewart 		break;
188*9bce0f05SLawrence Stewart 	case SYSCLOCK_FFWD:
189*9bce0f05SLawrence Stewart 		strlcpy(newclock, sysclocks[SYSCLOCK_FFWD], sizeof(newclock));
190*9bce0f05SLawrence Stewart 		break;
191*9bce0f05SLawrence Stewart 	}
192*9bce0f05SLawrence Stewart 
193*9bce0f05SLawrence Stewart 	error = sysctl_handle_string(oidp, &newclock[0], sizeof(newclock), req);
194*9bce0f05SLawrence Stewart 	if (error != 0 || req->newptr == NULL)
195*9bce0f05SLawrence Stewart 		return (error);
196*9bce0f05SLawrence Stewart 	if (strncmp(newclock, sysclocks[SYSCLOCK_FBCK],
197*9bce0f05SLawrence Stewart 	    sizeof(sysclocks[SYSCLOCK_FBCK])) == 0)
198*9bce0f05SLawrence Stewart 		sysclock_active = SYSCLOCK_FBCK;
199*9bce0f05SLawrence Stewart 	else if (strncmp(newclock, sysclocks[SYSCLOCK_FFWD],
200*9bce0f05SLawrence Stewart 	    sizeof(sysclocks[SYSCLOCK_FFWD])) == 0)
201*9bce0f05SLawrence Stewart 		sysclock_active = SYSCLOCK_FFWD;
202*9bce0f05SLawrence Stewart 	else
203*9bce0f05SLawrence Stewart 		return (EINVAL);
204*9bce0f05SLawrence Stewart 
205*9bce0f05SLawrence Stewart 	return (error);
206*9bce0f05SLawrence Stewart }
207*9bce0f05SLawrence Stewart 
208*9bce0f05SLawrence Stewart SYSCTL_PROC(_kern_ffclock, OID_AUTO, active, CTLTYPE_STRING | CTLFLAG_RW,
209*9bce0f05SLawrence Stewart     0, 0, sysctl_kern_ffclock_active, "A", "Kernel clock selected");
210*9bce0f05SLawrence Stewart 
211*9bce0f05SLawrence Stewart /*
212*9bce0f05SLawrence Stewart  * High level functions to access the Feed-Forward Clock.
213*9bce0f05SLawrence Stewart  */
214*9bce0f05SLawrence Stewart void
215*9bce0f05SLawrence Stewart ffclock_bintime(struct bintime *bt)
216*9bce0f05SLawrence Stewart {
217*9bce0f05SLawrence Stewart 
218*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC);
219*9bce0f05SLawrence Stewart }
220*9bce0f05SLawrence Stewart 
221*9bce0f05SLawrence Stewart void
222*9bce0f05SLawrence Stewart ffclock_nanotime(struct timespec *tsp)
223*9bce0f05SLawrence Stewart {
224*9bce0f05SLawrence Stewart 	struct bintime bt;
225*9bce0f05SLawrence Stewart 
226*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC);
227*9bce0f05SLawrence Stewart 	bintime2timespec(&bt, tsp);
228*9bce0f05SLawrence Stewart }
229*9bce0f05SLawrence Stewart 
230*9bce0f05SLawrence Stewart void
231*9bce0f05SLawrence Stewart ffclock_microtime(struct timeval *tvp)
232*9bce0f05SLawrence Stewart {
233*9bce0f05SLawrence Stewart 	struct bintime bt;
234*9bce0f05SLawrence Stewart 
235*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC);
236*9bce0f05SLawrence Stewart 	bintime2timeval(&bt, tvp);
237*9bce0f05SLawrence Stewart }
238*9bce0f05SLawrence Stewart 
239*9bce0f05SLawrence Stewart void
240*9bce0f05SLawrence Stewart ffclock_getbintime(struct bintime *bt)
241*9bce0f05SLawrence Stewart {
242*9bce0f05SLawrence Stewart 
243*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, bt, NULL,
244*9bce0f05SLawrence Stewart 	    FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST);
245*9bce0f05SLawrence Stewart }
246*9bce0f05SLawrence Stewart 
247*9bce0f05SLawrence Stewart void
248*9bce0f05SLawrence Stewart ffclock_getnanotime(struct timespec *tsp)
249*9bce0f05SLawrence Stewart {
250*9bce0f05SLawrence Stewart 	struct bintime bt;
251*9bce0f05SLawrence Stewart 
252*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, &bt, NULL,
253*9bce0f05SLawrence Stewart 	    FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST);
254*9bce0f05SLawrence Stewart 	bintime2timespec(&bt, tsp);
255*9bce0f05SLawrence Stewart }
256*9bce0f05SLawrence Stewart 
257*9bce0f05SLawrence Stewart void
258*9bce0f05SLawrence Stewart ffclock_getmicrotime(struct timeval *tvp)
259*9bce0f05SLawrence Stewart {
260*9bce0f05SLawrence Stewart 	struct bintime bt;
261*9bce0f05SLawrence Stewart 
262*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, &bt, NULL,
263*9bce0f05SLawrence Stewart 	    FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST);
264*9bce0f05SLawrence Stewart 	bintime2timeval(&bt, tvp);
265*9bce0f05SLawrence Stewart }
266*9bce0f05SLawrence Stewart 
267*9bce0f05SLawrence Stewart void
268*9bce0f05SLawrence Stewart ffclock_binuptime(struct bintime *bt)
269*9bce0f05SLawrence Stewart {
270*9bce0f05SLawrence Stewart 
271*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME);
272*9bce0f05SLawrence Stewart }
273*9bce0f05SLawrence Stewart 
274*9bce0f05SLawrence Stewart void
275*9bce0f05SLawrence Stewart ffclock_nanouptime(struct timespec *tsp)
276*9bce0f05SLawrence Stewart {
277*9bce0f05SLawrence Stewart 	struct bintime bt;
278*9bce0f05SLawrence Stewart 
279*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME);
280*9bce0f05SLawrence Stewart 	bintime2timespec(&bt, tsp);
281*9bce0f05SLawrence Stewart }
282*9bce0f05SLawrence Stewart 
283*9bce0f05SLawrence Stewart void
284*9bce0f05SLawrence Stewart ffclock_microuptime(struct timeval *tvp)
285*9bce0f05SLawrence Stewart {
286*9bce0f05SLawrence Stewart 	struct bintime bt;
287*9bce0f05SLawrence Stewart 
288*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME);
289*9bce0f05SLawrence Stewart 	bintime2timeval(&bt, tvp);
290*9bce0f05SLawrence Stewart }
291*9bce0f05SLawrence Stewart 
292*9bce0f05SLawrence Stewart void
293*9bce0f05SLawrence Stewart ffclock_getbinuptime(struct bintime *bt)
294*9bce0f05SLawrence Stewart {
295*9bce0f05SLawrence Stewart 
296*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, bt, NULL,
297*9bce0f05SLawrence Stewart 	    FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST);
298*9bce0f05SLawrence Stewart }
299*9bce0f05SLawrence Stewart 
300*9bce0f05SLawrence Stewart void
301*9bce0f05SLawrence Stewart ffclock_getnanouptime(struct timespec *tsp)
302*9bce0f05SLawrence Stewart {
303*9bce0f05SLawrence Stewart 	struct bintime bt;
304*9bce0f05SLawrence Stewart 
305*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, &bt, NULL,
306*9bce0f05SLawrence Stewart 	    FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST);
307*9bce0f05SLawrence Stewart 	bintime2timespec(&bt, tsp);
308*9bce0f05SLawrence Stewart }
309*9bce0f05SLawrence Stewart 
310*9bce0f05SLawrence Stewart void
311*9bce0f05SLawrence Stewart ffclock_getmicrouptime(struct timeval *tvp)
312*9bce0f05SLawrence Stewart {
313*9bce0f05SLawrence Stewart 	struct bintime bt;
314*9bce0f05SLawrence Stewart 
315*9bce0f05SLawrence Stewart 	ffclock_abstime(NULL, &bt, NULL,
316*9bce0f05SLawrence Stewart 	    FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST);
317*9bce0f05SLawrence Stewart 	bintime2timeval(&bt, tvp);
318*9bce0f05SLawrence Stewart }
319*9bce0f05SLawrence Stewart 
320*9bce0f05SLawrence Stewart void
321*9bce0f05SLawrence Stewart ffclock_bindifftime(ffcounter ffdelta, struct bintime *bt)
322*9bce0f05SLawrence Stewart {
323*9bce0f05SLawrence Stewart 
324*9bce0f05SLawrence Stewart 	ffclock_difftime(ffdelta, bt, NULL);
325*9bce0f05SLawrence Stewart }
326*9bce0f05SLawrence Stewart 
327*9bce0f05SLawrence Stewart void
328*9bce0f05SLawrence Stewart ffclock_nanodifftime(ffcounter ffdelta, struct timespec *tsp)
329*9bce0f05SLawrence Stewart {
330*9bce0f05SLawrence Stewart 	struct bintime bt;
331*9bce0f05SLawrence Stewart 
332*9bce0f05SLawrence Stewart 	ffclock_difftime(ffdelta, &bt, NULL);
333*9bce0f05SLawrence Stewart 	bintime2timespec(&bt, tsp);
334*9bce0f05SLawrence Stewart }
335*9bce0f05SLawrence Stewart 
336*9bce0f05SLawrence Stewart void
337*9bce0f05SLawrence Stewart ffclock_microdifftime(ffcounter ffdelta, struct timeval *tvp)
338*9bce0f05SLawrence Stewart {
339*9bce0f05SLawrence Stewart 	struct bintime bt;
340*9bce0f05SLawrence Stewart 
341*9bce0f05SLawrence Stewart 	ffclock_difftime(ffdelta, &bt, NULL);
342*9bce0f05SLawrence Stewart 	bintime2timeval(&bt, tvp);
343*9bce0f05SLawrence Stewart }
344