jcs's openbsd hax
openbsd
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}