jcs's openbsd hax
openbsd
at jcs 139 lines 3.1 kB view raw
1/* $OpenBSD: microtime.c,v 1.2 2022/07/23 22:58:51 cheloha Exp $ */ 2/* 3 * Copyright (c) 2000 Poul-Henning Kamp <phk@FreeBSD.org> 4 * Copyright (c) 2020 Paul Irofti <paul@irofti.net> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/types.h> 20#include <sys/atomic.h> 21#include <sys/timetc.h> 22 23#include <time.h> 24 25/* 26 * Return the difference between the timehands' counter value now and what 27 * was when we copied it to the timehands' offset_count. 28 */ 29static inline int 30tc_delta(struct timekeep *tk, u_int *delta) 31{ 32 u_int tc; 33 34 if (_tc_get_timecount(tk, &tc)) 35 return -1; 36 *delta = (tc - tk->tk_offset_count) & tk->tk_counter_mask; 37 return 0; 38} 39 40static int 41binuptime(struct bintime *bt, struct timekeep *tk) 42{ 43 u_int gen, delta; 44 45 do { 46 gen = tk->tk_generation; 47 membar_consumer(); 48 if (tc_delta(tk, &delta)) 49 return -1; 50 TIMECOUNT_TO_BINTIME(delta, tk->tk_scale, bt); 51 bintimeadd(bt, &tk->tk_offset, bt); 52 membar_consumer(); 53 } while (gen == 0 || gen != tk->tk_generation); 54 55 return 0; 56} 57 58static int 59binruntime(struct bintime *bt, struct timekeep *tk) 60{ 61 u_int gen, delta; 62 63 do { 64 gen = tk->tk_generation; 65 membar_consumer(); 66 if (tc_delta(tk, &delta)) 67 return -1; 68 TIMECOUNT_TO_BINTIME(delta, tk->tk_scale, bt); 69 bintimeadd(bt, &tk->tk_offset, bt); 70 bintimesub(bt, &tk->tk_naptime, bt); 71 membar_consumer(); 72 } while (gen == 0 || gen != tk->tk_generation); 73 74 return 0; 75} 76 77static int 78bintime(struct bintime *bt, struct timekeep *tk) 79{ 80 u_int gen, delta; 81 82 do { 83 gen = tk->tk_generation; 84 membar_consumer(); 85 if (tc_delta(tk, &delta)) 86 return -1; 87 TIMECOUNT_TO_BINTIME(delta, tk->tk_scale, bt); 88 bintimeadd(bt, &tk->tk_offset, bt); 89 bintimeadd(bt, &tk->tk_boottime, bt); 90 membar_consumer(); 91 } while (gen == 0 || gen != tk->tk_generation); 92 93 return 0; 94} 95 96int 97_microtime(struct timeval *tvp, struct timekeep *tk) 98{ 99 struct bintime bt; 100 101 if (bintime(&bt, tk)) 102 return -1; 103 BINTIME_TO_TIMEVAL(&bt, tvp); 104 return 0; 105} 106 107int 108_nanotime(struct timespec *tsp, struct timekeep *tk) 109{ 110 struct bintime bt; 111 112 if (bintime(&bt, tk)) 113 return -1; 114 BINTIME_TO_TIMESPEC(&bt, tsp); 115 return 0; 116} 117 118int 119_nanoruntime(struct timespec *ts, struct timekeep *tk) 120{ 121 struct bintime bt; 122 123 if (binruntime(&bt, tk)) 124 return -1; 125 BINTIME_TO_TIMESPEC(&bt, ts); 126 return 0; 127} 128 129 130int 131_nanouptime(struct timespec *tsp, struct timekeep *tk) 132{ 133 struct bintime bt; 134 135 if (binuptime(&bt, tk)) 136 return -1; 137 BINTIME_TO_TIMESPEC(&bt, tsp); 138 return 0; 139}