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