1 /* $NetBSD: timevar.h,v 1.52 2024/12/22 23:24:20 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 ppsratecheck(struct timeval *, int *, int); 206 int ratecheck(struct timeval *, const struct timeval *); 207 int settime(struct proc *p, struct timespec *); 208 int nanosleep1(struct lwp *, clockid_t, int, struct timespec *, 209 struct timespec *); 210 int settimeofday1(const struct timeval *, bool, 211 const void *, struct lwp *, bool); 212 int timer_create1(timer_t *, clockid_t, struct sigevent *, copyin_t, 213 struct lwp *); 214 int inittimeleft(struct timespec *, struct timespec *); 215 int gettimeleft(struct timespec *, struct timespec *); 216 void timerupcall(struct lwp *); 217 void time_init(void); 218 bool time_wraps(struct timespec *, struct timespec *); 219 220 void itimer_init(struct itimer *, const struct itimer_ops *, 221 clockid_t, struct itlist *); 222 void itimer_poison(struct itimer *); 223 void itimer_fini(struct itimer *); 224 225 void itimer_lock(void); 226 void itimer_unlock(void); 227 bool itimer_lock_held(void); /* for diagnostic assertions only */ 228 int itimer_settime(struct itimer *); 229 void itimer_gettime(const struct itimer *, struct itimerspec *); 230 231 void ptimer_tick(struct lwp *, bool); 232 void ptimers_free(struct proc *, int); 233 234 #define time_second getrealtime() 235 #define time_uptime getuptime() 236 #define time_uptime32 getuptime32() 237 238 #ifdef __HAVE_ATOMIC64_LOADSTORE 239 240 extern volatile time_t time__second; /* current second in the epoch */ 241 extern volatile time_t time__uptime; /* system uptime in seconds */ 242 243 static inline time_t 244 getrealtime(void) 245 { 246 return atomic_load_relaxed(&time__second); 247 } 248 249 static inline time_t 250 getuptime(void) 251 { 252 return atomic_load_relaxed(&time__uptime); 253 } 254 255 static inline time_t 256 getboottime(void) 257 { 258 return getrealtime() - getuptime(); 259 } 260 261 static inline uint32_t 262 getuptime32(void) 263 { 264 return getuptime() & 0xffffffff; 265 } 266 267 #else 268 269 time_t getrealtime(void); 270 time_t getuptime(void); 271 time_t getboottime(void); 272 uint32_t getuptime32(void); 273 274 #endif 275 276 extern int time_adjusted; 277 278 #define DEFAULT_TIMEOUT_EPSILON \ 279 (&(const struct bintime) { \ 280 .sec = 0, \ 281 .frac = ((uint64_t)1 << 32)/hz << 32, \ 282 }) 283 284 static __inline time_t time_mono_to_wall(time_t t) 285 { 286 287 return t + getboottime(); 288 } 289 290 static __inline time_t time_wall_to_mono(time_t t) 291 { 292 293 return t - getboottime(); 294 } 295 296 #endif /* !_SYS_TIMEVAR_H_ */ 297