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