xref: /netbsd/sys/sys/timevar.h (revision 3742054b)
1 /*	$NetBSD: timevar.h,v 1.51 2023/07/17 13:44:24 riastradh Exp $	*/
2 
3 /*
4  *  Copyright (c) 2005, 2008, 2020 The NetBSD Foundation, Inc.
5  *  All rights reserved.
6  *
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions
9  *  are met:
10  *  1. Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  *  2. Redistributions in binary form must reproduce the above copyright
13  *     notice, this list of conditions and the following disclaimer in the
14  *     documentation and/or other materials provided with the distribution.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  *  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  *  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  *  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  *  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * Copyright (c) 1982, 1986, 1993
31  *	The Regents of the University of California.  All rights reserved.
32  *
33  * Redistribution and use in source and binary forms, with or without
34  * modification, are permitted provided that the following conditions
35  * are met:
36  * 1. Redistributions of source code must retain the above copyright
37  *    notice, this list of conditions and the following disclaimer.
38  * 2. Redistributions in binary form must reproduce the above copyright
39  *    notice, this list of conditions and the following disclaimer in the
40  *    documentation and/or other materials provided with the distribution.
41  * 3. Neither the name of the University nor the names of its contributors
42  *    may be used to endorse or promote products derived from this software
43  *    without specific prior written permission.
44  *
45  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55  * SUCH DAMAGE.
56  *
57  *	@(#)time.h	8.5 (Berkeley) 5/4/95
58  */
59 
60 #ifndef _SYS_TIMEVAR_H_
61 #define _SYS_TIMEVAR_H_
62 
63 #include <sys/atomic.h>
64 #include <sys/callout.h>
65 #include <sys/queue.h>
66 #include <sys/signal.h>
67 #include <sys/systm.h>
68 
69 struct itimer;
70 LIST_HEAD(itlist, itimer);
71 
72 /*
73  * Interval timer operations vector.
74  *
75  * Required fields:
76  *
77  *	- ito_fire: A function to be called when the itimer fires.
78  *	  The timer implementation should perform whatever processing
79  *	  is necessary for that timer type.
80  *
81  * Optional fields:
82  *
83  *	- ito_realtime_changed: A function that is called when the system
84  *	  time (CLOCK_REALTIME) is called.
85  */
86 struct itimer_ops {
87 	void	(*ito_fire)(struct itimer *);
88 	void	(*ito_realtime_changed)(struct itimer *);
89 };
90 
91 /*
92  * Common interval timer data.
93  */
94 struct itimer {
95 	union {
96 		struct {
97 			callout_t		it_ch;
98 			LIST_ENTRY(itimer)	it_rtchgq;
99 		} it_real;
100 		struct {
101 			struct itlist		*it_vlist;
102 			LIST_ENTRY(itimer)	it_list;
103 			bool			it_active;
104 		} it_virtual;
105 	};
106 	const struct itimer_ops *it_ops;
107 	struct itimerspec it_time;
108 	clockid_t it_clockid;
109 	int	it_overruns;	/* Overruns currently accumulating */
110 	bool	it_dying;
111 };
112 
113 #define	it_ch		it_real.it_ch
114 #define	it_rtchgq	it_real.it_rtchgq
115 
116 #define	it_vlist	it_virtual.it_vlist
117 #define	it_list		it_virtual.it_list
118 #define	it_active	it_virtual.it_active
119 
120 /*
121  * Structure used to manage timers in a process.
122  */
123 struct ptimer {
124 	struct itimer pt_itimer;/* common interval timer data */
125 
126 	TAILQ_ENTRY(ptimer) pt_chain; /* link in signalling queue */
127 	struct	sigevent pt_ev;	/* event notification info */
128 	int	pt_poverruns;	/* Overruns associated w/ a delivery */
129 	int	pt_entry;	/* slot in proc's timer table */
130 	struct proc *pt_proc;	/* associated process */
131 	bool	pt_queued;	/* true if linked into signalling queue */
132 };
133 
134 #define	TIMER_MIN	4	/* [0..3] are reserved for setitimer(2) */
135 				/* REAL=0,VIRTUAL=1,PROF=2,MONOTONIC=3 */
136 #define	TIMER_MAX	36	/* 32 is minimum user timers per POSIX */
137 #define	TIMERS_ALL	0
138 #define	TIMERS_POSIX	1
139 
140 struct ptimers {
141 	struct itlist pts_virtual;
142 	struct itlist pts_prof;
143 	struct itimer *pts_timers[TIMER_MAX];
144 };
145 
146 /*
147  * Functions for looking at our clock: [get]{bin,nano,micro}[up]time()
148  *
149  * Functions without the "get" prefix returns the best timestamp
150  * we can produce in the given format.
151  *
152  * "bin"   == struct bintime  == seconds + 64 bit fraction of seconds.
153  * "nano"  == struct timespec == seconds + nanoseconds.
154  * "micro" == struct timeval  == seconds + microseconds.
155  *
156  * Functions containing "up" returns time relative to boot and
157  * should be used for calculating time intervals.
158  *
159  * Functions without "up" returns GMT time.
160  *
161  * Functions with the "get" prefix returns a less precise result
162  * much faster than the functions without "get" prefix and should
163  * be used where a precision of 1/HZ (eg 10 msec on a 100HZ machine)
164  * is acceptable or where performance is priority.
165  * (NB: "precision", _not_ "resolution" !)
166  *
167  */
168 
169 void	binuptime(struct bintime *);
170 void	nanouptime(struct timespec *);
171 void	microuptime(struct timeval *);
172 
173 void	bintime(struct bintime *);
174 void	nanotime(struct timespec *);
175 void	microtime(struct timeval *);
176 
177 void	getbinuptime(struct bintime *);
178 void	getnanouptime(struct timespec *);
179 void	getmicrouptime(struct timeval *);
180 
181 void	getbintime(struct bintime *);
182 void	getnanotime(struct timespec *);
183 void	getmicrotime(struct timeval *);
184 
185 void	getbinboottime(struct bintime *);
186 void	getnanoboottime(struct timespec *);
187 void	getmicroboottime(struct timeval *);
188 
189 /* Other functions */
190 int	ts2timo(clockid_t, int, struct timespec *, int *, struct timespec *);
191 void	adjtime1(const struct timeval *, struct timeval *, struct proc *);
192 int	clock_getres1(clockid_t, struct timespec *);
193 int	clock_gettime1(clockid_t, struct timespec *);
194 int	clock_settime1(struct proc *, clockid_t, const struct timespec *, bool);
195 void	clock_timeleft(clockid_t, struct timespec *, struct timespec *);
196 int	dogetitimer(struct proc *, int, struct itimerval *);
197 int	dosetitimer(struct proc *, int, struct itimerval *);
198 int	dotimer_gettime(int, struct proc *, struct itimerspec *);
199 int	dotimer_settime(int, struct itimerspec *, struct itimerspec *, int,
200 	    struct proc *);
201 int	tshzto(const struct timespec *);
202 int	tshztoup(const struct timespec *);
203 int	tvhzto(const struct timeval *);
204 void	inittimecounter(void);
205 int	itimerfix(struct timeval *);
206 int	itimespecfix(struct timespec *);
207 int	ppsratecheck(struct timeval *, int *, int);
208 int	ratecheck(struct timeval *, const struct timeval *);
209 int	settime(struct proc *p, struct timespec *);
210 int	nanosleep1(struct lwp *, clockid_t, int, struct timespec *,
211 	    struct timespec *);
212 int	settimeofday1(const struct timeval *, bool,
213 	    const void *, struct lwp *, bool);
214 int	timer_create1(timer_t *, clockid_t, struct sigevent *, copyin_t,
215 	    struct lwp *);
216 int	tstohz(const struct timespec *);
217 int	tvtohz(const struct timeval *);
218 int	inittimeleft(struct timespec *, struct timespec *);
219 int	gettimeleft(struct timespec *, struct timespec *);
220 void	timerupcall(struct lwp *);
221 void	time_init(void);
222 bool	time_wraps(struct timespec *, struct timespec *);
223 
224 void	itimer_init(struct itimer *, const struct itimer_ops *,
225 	    clockid_t, struct itlist *);
226 void	itimer_poison(struct itimer *);
227 void	itimer_fini(struct itimer *);
228 
229 void	itimer_lock(void);
230 void	itimer_unlock(void);
231 bool	itimer_lock_held(void);		/* for diagnostic assertions only */
232 int	itimer_settime(struct itimer *);
233 void	itimer_gettime(const struct itimer *, struct itimerspec *);
234 
235 void	ptimer_tick(struct lwp *, bool);
236 void	ptimers_free(struct proc *, int);
237 
238 #define	time_second	getrealtime()
239 #define	time_uptime	getuptime()
240 #define	time_uptime32	getuptime32()
241 
242 #ifdef __HAVE_ATOMIC64_LOADSTORE
243 
244 extern volatile time_t time__second;	/* current second in the epoch */
245 extern volatile time_t time__uptime;	/* system uptime in seconds */
246 
247 static inline time_t
getrealtime(void)248 getrealtime(void)
249 {
250 	return atomic_load_relaxed(&time__second);
251 }
252 
253 static inline time_t
getuptime(void)254 getuptime(void)
255 {
256 	return atomic_load_relaxed(&time__uptime);
257 }
258 
259 static inline time_t
getboottime(void)260 getboottime(void)
261 {
262 	return getrealtime() - getuptime();
263 }
264 
265 static inline uint32_t
getuptime32(void)266 getuptime32(void)
267 {
268 	return getuptime() & 0xffffffff;
269 }
270 
271 #else
272 
273 time_t		getrealtime(void);
274 time_t		getuptime(void);
275 time_t		getboottime(void);
276 uint32_t	getuptime32(void);
277 
278 #endif
279 
280 extern int time_adjusted;
281 
282 #define	DEFAULT_TIMEOUT_EPSILON						      \
283 	(&(const struct bintime) {					      \
284 		.sec = 0,						      \
285 		.frac = ((uint64_t)1 << 32)/hz << 32,			      \
286 	})
287 
time_mono_to_wall(time_t t)288 static __inline time_t time_mono_to_wall(time_t t)
289 {
290 
291 	return t + getboottime();
292 }
293 
time_wall_to_mono(time_t t)294 static __inline time_t time_wall_to_mono(time_t t)
295 {
296 
297 	return t - getboottime();
298 }
299 
300 #endif /* !_SYS_TIMEVAR_H_ */
301