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