1 1.228 pho /* $NetBSD: kern_time.c,v 1.228 2025/03/19 14:27:05 pho Exp $ */ 2 1.42 cgd 3 1.42 cgd /*- 4 1.207 thorpej * Copyright (c) 2000, 2004, 2005, 2007, 2008, 2009, 2020 5 1.207 thorpej * The NetBSD Foundation, Inc. 6 1.42 cgd * All rights reserved. 7 1.42 cgd * 8 1.42 cgd * This code is derived from software contributed to The NetBSD Foundation 9 1.207 thorpej * by Christopher G. Demetriou, by Andrew Doran, and by Jason R. Thorpe. 10 1.42 cgd * 11 1.42 cgd * Redistribution and use in source and binary forms, with or without 12 1.42 cgd * modification, are permitted provided that the following conditions 13 1.42 cgd * are met: 14 1.42 cgd * 1. Redistributions of source code must retain the above copyright 15 1.42 cgd * notice, this list of conditions and the following disclaimer. 16 1.42 cgd * 2. Redistributions in binary form must reproduce the above copyright 17 1.42 cgd * notice, this list of conditions and the following disclaimer in the 18 1.42 cgd * documentation and/or other materials provided with the distribution. 19 1.42 cgd * 20 1.42 cgd * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.42 cgd * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.42 cgd * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.42 cgd * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.42 cgd * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.42 cgd * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.42 cgd * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.42 cgd * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.42 cgd * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.42 cgd * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.42 cgd * POSSIBILITY OF SUCH DAMAGE. 31 1.42 cgd */ 32 1.9 cgd 33 1.1 cgd /* 34 1.8 cgd * Copyright (c) 1982, 1986, 1989, 1993 35 1.8 cgd * The Regents of the University of California. All rights reserved. 36 1.1 cgd * 37 1.1 cgd * Redistribution and use in source and binary forms, with or without 38 1.1 cgd * modification, are permitted provided that the following conditions 39 1.1 cgd * are met: 40 1.1 cgd * 1. Redistributions of source code must retain the above copyright 41 1.1 cgd * notice, this list of conditions and the following disclaimer. 42 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 43 1.1 cgd * notice, this list of conditions and the following disclaimer in the 44 1.1 cgd * documentation and/or other materials provided with the distribution. 45 1.72 agc * 3. Neither the name of the University nor the names of its contributors 46 1.1 cgd * may be used to endorse or promote products derived from this software 47 1.1 cgd * without specific prior written permission. 48 1.1 cgd * 49 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 1.1 cgd * SUCH DAMAGE. 60 1.1 cgd * 61 1.33 fvdl * @(#)kern_time.c 8.4 (Berkeley) 5/26/95 62 1.1 cgd */ 63 1.58 lukem 64 1.58 lukem #include <sys/cdefs.h> 65 1.228 pho __KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.228 2025/03/19 14:27:05 pho Exp $"); 66 1.1 cgd 67 1.5 mycroft #include <sys/param.h> 68 1.225 riastrad #include <sys/types.h> 69 1.225 riastrad 70 1.225 riastrad #include <sys/callout.h> 71 1.225 riastrad #include <sys/cpu.h> 72 1.225 riastrad #include <sys/errno.h> 73 1.225 riastrad #include <sys/intr.h> 74 1.225 riastrad #include <sys/kauth.h> 75 1.5 mycroft #include <sys/kernel.h> 76 1.225 riastrad #include <sys/kmem.h> 77 1.225 riastrad #include <sys/lwp.h> 78 1.225 riastrad #include <sys/mount.h> 79 1.225 riastrad #include <sys/mutex.h> 80 1.5 mycroft #include <sys/proc.h> 81 1.225 riastrad #include <sys/queue.h> 82 1.225 riastrad #include <sys/resourcevar.h> 83 1.225 riastrad #include <sys/signal.h> 84 1.17 christos #include <sys/signalvar.h> 85 1.225 riastrad #include <sys/syscallargs.h> 86 1.25 perry #include <sys/syslog.h> 87 1.225 riastrad #include <sys/systm.h> 88 1.101 kardel #include <sys/timetc.h> 89 1.218 riastrad #include <sys/timevar.h> 90 1.143 ad #include <sys/timex.h> 91 1.225 riastrad #include <sys/vnode.h> 92 1.225 riastrad 93 1.225 riastrad #include <machine/limits.h> 94 1.19 christos 95 1.210 thorpej kmutex_t itimer_mutex __cacheline_aligned; /* XXX static */ 96 1.207 thorpej static struct itlist itimer_realtime_changed_notify; 97 1.142 ad 98 1.220 riastrad static void itimer_callout(void *); 99 1.207 thorpej static void ptimer_intr(void *); 100 1.207 thorpej static void *ptimer_sih __read_mostly; 101 1.210 thorpej static TAILQ_HEAD(, ptimer) ptimer_queue; 102 1.97 simonb 103 1.168 yamt #define CLOCK_VIRTUAL_P(clockid) \ 104 1.168 yamt ((clockid) == CLOCK_VIRTUAL || (clockid) == CLOCK_PROF) 105 1.168 yamt 106 1.168 yamt CTASSERT(ITIMER_REAL == CLOCK_REALTIME); 107 1.168 yamt CTASSERT(ITIMER_VIRTUAL == CLOCK_VIRTUAL); 108 1.168 yamt CTASSERT(ITIMER_PROF == CLOCK_PROF); 109 1.170 christos CTASSERT(ITIMER_MONOTONIC == CLOCK_MONOTONIC); 110 1.168 yamt 111 1.131 ad /* 112 1.131 ad * Initialize timekeeping. 113 1.131 ad */ 114 1.131 ad void 115 1.131 ad time_init(void) 116 1.131 ad { 117 1.131 ad 118 1.207 thorpej mutex_init(&itimer_mutex, MUTEX_DEFAULT, IPL_SCHED); 119 1.207 thorpej LIST_INIT(&itimer_realtime_changed_notify); 120 1.207 thorpej 121 1.207 thorpej TAILQ_INIT(&ptimer_queue); 122 1.207 thorpej ptimer_sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE, 123 1.207 thorpej ptimer_intr, NULL); 124 1.207 thorpej } 125 1.207 thorpej 126 1.207 thorpej /* 127 1.207 thorpej * Check if the time will wrap if set to ts. 128 1.207 thorpej * 129 1.207 thorpej * ts - timespec describing the new time 130 1.207 thorpej * delta - the delta between the current time and ts 131 1.207 thorpej */ 132 1.207 thorpej bool 133 1.207 thorpej time_wraps(struct timespec *ts, struct timespec *delta) 134 1.207 thorpej { 135 1.207 thorpej 136 1.207 thorpej /* 137 1.207 thorpej * Don't allow the time to be set forward so far it 138 1.207 thorpej * will wrap and become negative, thus allowing an 139 1.207 thorpej * attacker to bypass the next check below. The 140 1.207 thorpej * cutoff is 1 year before rollover occurs, so even 141 1.207 thorpej * if the attacker uses adjtime(2) to move the time 142 1.207 thorpej * past the cutoff, it will take a very long time 143 1.207 thorpej * to get to the wrap point. 144 1.207 thorpej */ 145 1.207 thorpej if ((ts->tv_sec > LLONG_MAX - 365*24*60*60) || 146 1.207 thorpej (delta->tv_sec < 0 || delta->tv_nsec < 0)) 147 1.207 thorpej return true; 148 1.207 thorpej 149 1.207 thorpej return false; 150 1.207 thorpej } 151 1.207 thorpej 152 1.207 thorpej /* 153 1.207 thorpej * itimer_lock: 154 1.207 thorpej * 155 1.207 thorpej * Acquire the interval timer data lock. 156 1.207 thorpej */ 157 1.207 thorpej void 158 1.207 thorpej itimer_lock(void) 159 1.207 thorpej { 160 1.207 thorpej mutex_spin_enter(&itimer_mutex); 161 1.131 ad } 162 1.131 ad 163 1.207 thorpej /* 164 1.207 thorpej * itimer_unlock: 165 1.207 thorpej * 166 1.207 thorpej * Release the interval timer data lock. 167 1.207 thorpej */ 168 1.142 ad void 169 1.207 thorpej itimer_unlock(void) 170 1.142 ad { 171 1.207 thorpej mutex_spin_exit(&itimer_mutex); 172 1.207 thorpej } 173 1.142 ad 174 1.207 thorpej /* 175 1.207 thorpej * itimer_lock_held: 176 1.207 thorpej * 177 1.207 thorpej * Check that the interval timer lock is held for diagnostic 178 1.207 thorpej * assertions. 179 1.207 thorpej */ 180 1.210 thorpej inline bool __diagused 181 1.207 thorpej itimer_lock_held(void) 182 1.207 thorpej { 183 1.207 thorpej return mutex_owned(&itimer_mutex); 184 1.142 ad } 185 1.142 ad 186 1.207 thorpej /* 187 1.207 thorpej * Time of day and interval timer support. 188 1.1 cgd * 189 1.1 cgd * These routines provide the kernel entry points to get and set 190 1.1 cgd * the time-of-day and per-process interval timers. Subroutines 191 1.1 cgd * here provide support for adding and subtracting timeval structures 192 1.1 cgd * and decrementing interval timers, optionally reloading the interval 193 1.1 cgd * timers when they expire. 194 1.1 cgd */ 195 1.1 cgd 196 1.22 jtc /* This function is used by clock_settime and settimeofday */ 197 1.132 elad static int 198 1.156 christos settime1(struct proc *p, const struct timespec *ts, bool check_kauth) 199 1.22 jtc { 200 1.156 christos struct timespec delta, now; 201 1.22 jtc 202 1.206 nia /* 203 1.206 nia * The time being set to an unreasonable value will cause 204 1.206 nia * unreasonable system behaviour. 205 1.206 nia */ 206 1.206 nia if (ts->tv_sec < 0 || ts->tv_sec > (1LL << 36)) 207 1.217 riastrad return EINVAL; 208 1.206 nia 209 1.156 christos nanotime(&now); 210 1.156 christos timespecsub(ts, &now, &delta); 211 1.132 elad 212 1.134 elad if (check_kauth && kauth_authorize_system(kauth_cred_get(), 213 1.156 christos KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_SYSTEM, __UNCONST(ts), 214 1.156 christos &delta, KAUTH_ARG(check_kauth ? false : true)) != 0) { 215 1.217 riastrad return EPERM; 216 1.55 tron } 217 1.132 elad 218 1.29 tls #ifdef notyet 219 1.109 elad if ((delta.tv_sec < 86400) && securelevel > 0) { /* XXX elad - notyet */ 220 1.217 riastrad return EPERM; 221 1.55 tron } 222 1.29 tls #endif 223 1.103 kardel 224 1.156 christos tc_setclock(ts); 225 1.103 kardel 226 1.22 jtc resettodr(); 227 1.129 ad 228 1.207 thorpej /* 229 1.207 thorpej * Notify pending CLOCK_REALTIME timers about the real time change. 230 1.207 thorpej * There may be inactive timers on this list, but this happens 231 1.207 thorpej * comparatively less often than timers firing, and so it's better 232 1.207 thorpej * to put the extra checks here than to complicate the other code 233 1.207 thorpej * path. 234 1.207 thorpej */ 235 1.207 thorpej struct itimer *it; 236 1.207 thorpej itimer_lock(); 237 1.207 thorpej LIST_FOREACH(it, &itimer_realtime_changed_notify, it_rtchgq) { 238 1.207 thorpej KASSERT(it->it_ops->ito_realtime_changed != NULL); 239 1.207 thorpej if (timespecisset(&it->it_time.it_value)) { 240 1.207 thorpej (*it->it_ops->ito_realtime_changed)(it); 241 1.207 thorpej } 242 1.207 thorpej } 243 1.207 thorpej itimer_unlock(); 244 1.207 thorpej 245 1.217 riastrad return 0; 246 1.22 jtc } 247 1.22 jtc 248 1.132 elad int 249 1.132 elad settime(struct proc *p, struct timespec *ts) 250 1.132 elad { 251 1.217 riastrad return settime1(p, ts, true); 252 1.132 elad } 253 1.132 elad 254 1.22 jtc /* ARGSUSED */ 255 1.22 jtc int 256 1.156 christos sys___clock_gettime50(struct lwp *l, 257 1.156 christos const struct sys___clock_gettime50_args *uap, register_t *retval) 258 1.22 jtc { 259 1.135 dsl /* { 260 1.22 jtc syscallarg(clockid_t) clock_id; 261 1.23 cgd syscallarg(struct timespec *) tp; 262 1.135 dsl } */ 263 1.165 njoly int error; 264 1.22 jtc struct timespec ats; 265 1.22 jtc 266 1.165 njoly error = clock_gettime1(SCARG(uap, clock_id), &ats); 267 1.165 njoly if (error != 0) 268 1.165 njoly return error; 269 1.165 njoly 270 1.165 njoly return copyout(&ats, SCARG(uap, tp), sizeof(ats)); 271 1.165 njoly } 272 1.165 njoly 273 1.22 jtc /* ARGSUSED */ 274 1.22 jtc int 275 1.156 christos sys___clock_settime50(struct lwp *l, 276 1.156 christos const struct sys___clock_settime50_args *uap, register_t *retval) 277 1.22 jtc { 278 1.135 dsl /* { 279 1.22 jtc syscallarg(clockid_t) clock_id; 280 1.23 cgd syscallarg(const struct timespec *) tp; 281 1.135 dsl } */ 282 1.156 christos int error; 283 1.156 christos struct timespec ats; 284 1.22 jtc 285 1.156 christos if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0) 286 1.156 christos return error; 287 1.156 christos 288 1.156 christos return clock_settime1(l->l_proc, SCARG(uap, clock_id), &ats, true); 289 1.56 manu } 290 1.56 manu 291 1.56 manu 292 1.56 manu int 293 1.132 elad clock_settime1(struct proc *p, clockid_t clock_id, const struct timespec *tp, 294 1.132 elad bool check_kauth) 295 1.56 manu { 296 1.56 manu int error; 297 1.56 manu 298 1.201 kamil if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000L) 299 1.201 kamil return EINVAL; 300 1.201 kamil 301 1.61 simonb switch (clock_id) { 302 1.61 simonb case CLOCK_REALTIME: 303 1.156 christos if ((error = settime1(p, tp, check_kauth)) != 0) 304 1.217 riastrad return error; 305 1.61 simonb break; 306 1.61 simonb case CLOCK_MONOTONIC: 307 1.217 riastrad return EINVAL; /* read-only clock */ 308 1.61 simonb default: 309 1.217 riastrad return EINVAL; 310 1.61 simonb } 311 1.22 jtc 312 1.22 jtc return 0; 313 1.22 jtc } 314 1.22 jtc 315 1.22 jtc int 316 1.156 christos sys___clock_getres50(struct lwp *l, const struct sys___clock_getres50_args *uap, 317 1.140 yamt register_t *retval) 318 1.22 jtc { 319 1.135 dsl /* { 320 1.22 jtc syscallarg(clockid_t) clock_id; 321 1.23 cgd syscallarg(struct timespec *) tp; 322 1.135 dsl } */ 323 1.22 jtc struct timespec ts; 324 1.180 maxv int error; 325 1.22 jtc 326 1.164 njoly if ((error = clock_getres1(SCARG(uap, clock_id), &ts)) != 0) 327 1.164 njoly return error; 328 1.164 njoly 329 1.164 njoly if (SCARG(uap, tp)) 330 1.164 njoly error = copyout(&ts, SCARG(uap, tp), sizeof(ts)); 331 1.164 njoly 332 1.164 njoly return error; 333 1.164 njoly } 334 1.164 njoly 335 1.164 njoly int 336 1.164 njoly clock_getres1(clockid_t clock_id, struct timespec *ts) 337 1.164 njoly { 338 1.164 njoly 339 1.61 simonb switch (clock_id) { 340 1.61 simonb case CLOCK_REALTIME: 341 1.61 simonb case CLOCK_MONOTONIC: 342 1.228 pho case CLOCK_PROCESS_CPUTIME_ID: 343 1.228 pho case CLOCK_THREAD_CPUTIME_ID: 344 1.164 njoly ts->tv_sec = 0; 345 1.102 kardel if (tc_getfrequency() > 1000000000) 346 1.164 njoly ts->tv_nsec = 1; 347 1.102 kardel else 348 1.164 njoly ts->tv_nsec = 1000000000 / tc_getfrequency(); 349 1.61 simonb break; 350 1.61 simonb default: 351 1.164 njoly return EINVAL; 352 1.61 simonb } 353 1.22 jtc 354 1.164 njoly return 0; 355 1.22 jtc } 356 1.22 jtc 357 1.27 jtc /* ARGSUSED */ 358 1.27 jtc int 359 1.156 christos sys___nanosleep50(struct lwp *l, const struct sys___nanosleep50_args *uap, 360 1.140 yamt register_t *retval) 361 1.27 jtc { 362 1.135 dsl /* { 363 1.101 kardel syscallarg(struct timespec *) rqtp; 364 1.101 kardel syscallarg(struct timespec *) rmtp; 365 1.135 dsl } */ 366 1.101 kardel struct timespec rmt, rqt; 367 1.120 dsl int error, error1; 368 1.101 kardel 369 1.101 kardel error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec)); 370 1.101 kardel if (error) 371 1.217 riastrad return error; 372 1.101 kardel 373 1.175 christos error = nanosleep1(l, CLOCK_MONOTONIC, 0, &rqt, 374 1.175 christos SCARG(uap, rmtp) ? &rmt : NULL); 375 1.175 christos if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR)) 376 1.175 christos return error; 377 1.175 christos 378 1.175 christos error1 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt)); 379 1.175 christos return error1 ? error1 : error; 380 1.175 christos } 381 1.175 christos 382 1.175 christos /* ARGSUSED */ 383 1.175 christos int 384 1.175 christos sys_clock_nanosleep(struct lwp *l, const struct sys_clock_nanosleep_args *uap, 385 1.175 christos register_t *retval) 386 1.175 christos { 387 1.175 christos /* { 388 1.175 christos syscallarg(clockid_t) clock_id; 389 1.175 christos syscallarg(int) flags; 390 1.175 christos syscallarg(struct timespec *) rqtp; 391 1.175 christos syscallarg(struct timespec *) rmtp; 392 1.175 christos } */ 393 1.175 christos struct timespec rmt, rqt; 394 1.175 christos int error, error1; 395 1.175 christos 396 1.175 christos error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec)); 397 1.175 christos if (error) 398 1.181 christos goto out; 399 1.175 christos 400 1.175 christos error = nanosleep1(l, SCARG(uap, clock_id), SCARG(uap, flags), &rqt, 401 1.175 christos SCARG(uap, rmtp) ? &rmt : NULL); 402 1.120 dsl if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR)) 403 1.181 christos goto out; 404 1.120 dsl 405 1.189 njoly if ((SCARG(uap, flags) & TIMER_ABSTIME) == 0 && 406 1.189 njoly (error1 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt))) != 0) 407 1.181 christos error = error1; 408 1.181 christos out: 409 1.181 christos *retval = error; 410 1.181 christos return 0; 411 1.120 dsl } 412 1.120 dsl 413 1.120 dsl int 414 1.175 christos nanosleep1(struct lwp *l, clockid_t clock_id, int flags, struct timespec *rqt, 415 1.175 christos struct timespec *rmt) 416 1.120 dsl { 417 1.141 yamt struct timespec rmtstart; 418 1.120 dsl int error, timo; 419 1.120 dsl 420 1.184 uwe if ((error = ts2timo(clock_id, flags, rqt, &timo, &rmtstart)) != 0) { 421 1.184 uwe if (error == ETIMEDOUT) { 422 1.184 uwe error = 0; 423 1.184 uwe if (rmt != NULL) 424 1.184 uwe rmt->tv_sec = rmt->tv_nsec = 0; 425 1.184 uwe } 426 1.184 uwe return error; 427 1.184 uwe } 428 1.101 kardel 429 1.101 kardel /* 430 1.175 christos * Avoid inadvertently sleeping forever 431 1.101 kardel */ 432 1.101 kardel if (timo == 0) 433 1.101 kardel timo = 1; 434 1.141 yamt again: 435 1.141 yamt error = kpause("nanoslp", true, timo, NULL); 436 1.197 kre if (error == EWOULDBLOCK) 437 1.197 kre error = 0; 438 1.141 yamt if (rmt != NULL || error == 0) { 439 1.141 yamt struct timespec rmtend; 440 1.141 yamt struct timespec t0; 441 1.141 yamt struct timespec *t; 442 1.204 maxv int err; 443 1.204 maxv 444 1.204 maxv err = clock_gettime1(clock_id, &rmtend); 445 1.204 maxv if (err != 0) 446 1.204 maxv return err; 447 1.101 kardel 448 1.141 yamt t = (rmt != NULL) ? rmt : &t0; 449 1.179 christos if (flags & TIMER_ABSTIME) { 450 1.179 christos timespecsub(rqt, &rmtend, t); 451 1.179 christos } else { 452 1.213 riastrad if (timespeccmp(&rmtend, &rmtstart, <)) 453 1.213 riastrad timespecclear(t); /* clock wound back */ 454 1.213 riastrad else 455 1.213 riastrad timespecsub(&rmtend, &rmtstart, t); 456 1.213 riastrad if (timespeccmp(rqt, t, <)) 457 1.213 riastrad timespecclear(t); 458 1.213 riastrad else 459 1.213 riastrad timespecsub(rqt, t, t); 460 1.179 christos } 461 1.141 yamt if (t->tv_sec < 0) 462 1.141 yamt timespecclear(t); 463 1.141 yamt if (error == 0) { 464 1.141 yamt timo = tstohz(t); 465 1.141 yamt if (timo > 0) 466 1.141 yamt goto again; 467 1.141 yamt } 468 1.141 yamt } 469 1.104 kardel 470 1.101 kardel if (error == ERESTART) 471 1.101 kardel error = EINTR; 472 1.101 kardel 473 1.101 kardel return error; 474 1.27 jtc } 475 1.22 jtc 476 1.186 christos int 477 1.186 christos sys_clock_getcpuclockid2(struct lwp *l, 478 1.186 christos const struct sys_clock_getcpuclockid2_args *uap, 479 1.186 christos register_t *retval) 480 1.186 christos { 481 1.186 christos /* { 482 1.186 christos syscallarg(idtype_t idtype; 483 1.186 christos syscallarg(id_t id); 484 1.186 christos syscallarg(clockid_t *)clock_id; 485 1.186 christos } */ 486 1.186 christos pid_t pid; 487 1.186 christos lwpid_t lid; 488 1.186 christos clockid_t clock_id; 489 1.186 christos id_t id = SCARG(uap, id); 490 1.186 christos 491 1.186 christos switch (SCARG(uap, idtype)) { 492 1.186 christos case P_PID: 493 1.188 msaitoh pid = id == 0 ? l->l_proc->p_pid : id; 494 1.186 christos clock_id = CLOCK_PROCESS_CPUTIME_ID | pid; 495 1.186 christos break; 496 1.186 christos case P_LWPID: 497 1.186 christos lid = id == 0 ? l->l_lid : id; 498 1.186 christos clock_id = CLOCK_THREAD_CPUTIME_ID | lid; 499 1.186 christos break; 500 1.186 christos default: 501 1.186 christos return EINVAL; 502 1.186 christos } 503 1.186 christos return copyout(&clock_id, SCARG(uap, clock_id), sizeof(clock_id)); 504 1.186 christos } 505 1.186 christos 506 1.1 cgd /* ARGSUSED */ 507 1.3 andrew int 508 1.156 christos sys___gettimeofday50(struct lwp *l, const struct sys___gettimeofday50_args *uap, 509 1.140 yamt register_t *retval) 510 1.15 thorpej { 511 1.135 dsl /* { 512 1.11 cgd syscallarg(struct timeval *) tp; 513 1.135 dsl syscallarg(void *) tzp; really "struct timezone *"; 514 1.135 dsl } */ 515 1.1 cgd struct timeval atv; 516 1.1 cgd int error = 0; 517 1.25 perry struct timezone tzfake; 518 1.1 cgd 519 1.11 cgd if (SCARG(uap, tp)) { 520 1.190 maxv memset(&atv, 0, sizeof(atv)); 521 1.1 cgd microtime(&atv); 522 1.35 perry error = copyout(&atv, SCARG(uap, tp), sizeof(atv)); 523 1.17 christos if (error) 524 1.217 riastrad return error; 525 1.1 cgd } 526 1.25 perry if (SCARG(uap, tzp)) { 527 1.25 perry /* 528 1.32 mycroft * NetBSD has no kernel notion of time zone, so we just 529 1.25 perry * fake up a timezone struct and return it if demanded. 530 1.25 perry */ 531 1.25 perry tzfake.tz_minuteswest = 0; 532 1.25 perry tzfake.tz_dsttime = 0; 533 1.35 perry error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake)); 534 1.25 perry } 535 1.217 riastrad return error; 536 1.1 cgd } 537 1.1 cgd 538 1.1 cgd /* ARGSUSED */ 539 1.3 andrew int 540 1.156 christos sys___settimeofday50(struct lwp *l, const struct sys___settimeofday50_args *uap, 541 1.140 yamt register_t *retval) 542 1.15 thorpej { 543 1.135 dsl /* { 544 1.24 cgd syscallarg(const struct timeval *) tv; 545 1.140 yamt syscallarg(const void *) tzp; really "const struct timezone *"; 546 1.135 dsl } */ 547 1.60 manu 548 1.119 dsl return settimeofday1(SCARG(uap, tv), true, SCARG(uap, tzp), l, true); 549 1.60 manu } 550 1.60 manu 551 1.60 manu int 552 1.119 dsl settimeofday1(const struct timeval *utv, bool userspace, 553 1.119 dsl const void *utzp, struct lwp *l, bool check_kauth) 554 1.60 manu { 555 1.22 jtc struct timeval atv; 556 1.98 christos struct timespec ts; 557 1.22 jtc int error; 558 1.1 cgd 559 1.8 cgd /* Verify all parameters before changing time. */ 560 1.119 dsl 561 1.25 perry /* 562 1.32 mycroft * NetBSD has no kernel notion of time zone, and only an 563 1.25 perry * obsolete program would try to set it, so we log a warning. 564 1.25 perry */ 565 1.98 christos if (utzp) 566 1.25 perry log(LOG_WARNING, "pid %d attempted to set the " 567 1.119 dsl "(obsolete) kernel time zone\n", l->l_proc->p_pid); 568 1.98 christos 569 1.217 riastrad if (utv == NULL) 570 1.98 christos return 0; 571 1.98 christos 572 1.119 dsl if (userspace) { 573 1.119 dsl if ((error = copyin(utv, &atv, sizeof(atv))) != 0) 574 1.119 dsl return error; 575 1.119 dsl utv = &atv; 576 1.119 dsl } 577 1.119 dsl 578 1.200 kamil if (utv->tv_usec < 0 || utv->tv_usec >= 1000000) 579 1.200 kamil return EINVAL; 580 1.200 kamil 581 1.119 dsl TIMEVAL_TO_TIMESPEC(utv, &ts); 582 1.133 elad return settime1(l->l_proc, &ts, check_kauth); 583 1.1 cgd } 584 1.1 cgd 585 1.68 dsl int time_adjusted; /* set if an adjustment is made */ 586 1.1 cgd 587 1.1 cgd /* ARGSUSED */ 588 1.3 andrew int 589 1.156 christos sys___adjtime50(struct lwp *l, const struct sys___adjtime50_args *uap, 590 1.140 yamt register_t *retval) 591 1.15 thorpej { 592 1.135 dsl /* { 593 1.24 cgd syscallarg(const struct timeval *) delta; 594 1.11 cgd syscallarg(struct timeval *) olddelta; 595 1.135 dsl } */ 596 1.180 maxv int error; 597 1.156 christos struct timeval atv, oldatv; 598 1.1 cgd 599 1.106 elad if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME, 600 1.106 elad KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL, NULL)) != 0) 601 1.156 christos return error; 602 1.17 christos 603 1.156 christos if (SCARG(uap, delta)) { 604 1.156 christos error = copyin(SCARG(uap, delta), &atv, 605 1.156 christos sizeof(*SCARG(uap, delta))); 606 1.156 christos if (error) 607 1.217 riastrad return error; 608 1.156 christos } 609 1.156 christos adjtime1(SCARG(uap, delta) ? &atv : NULL, 610 1.156 christos SCARG(uap, olddelta) ? &oldatv : NULL, l->l_proc); 611 1.156 christos if (SCARG(uap, olddelta)) 612 1.156 christos error = copyout(&oldatv, SCARG(uap, olddelta), 613 1.156 christos sizeof(*SCARG(uap, olddelta))); 614 1.156 christos return error; 615 1.56 manu } 616 1.56 manu 617 1.156 christos void 618 1.110 yamt adjtime1(const struct timeval *delta, struct timeval *olddelta, struct proc *p) 619 1.56 manu { 620 1.101 kardel 621 1.101 kardel if (olddelta) { 622 1.194 maxv memset(olddelta, 0, sizeof(*olddelta)); 623 1.143 ad mutex_spin_enter(&timecounter_lock); 624 1.156 christos olddelta->tv_sec = time_adjtime / 1000000; 625 1.156 christos olddelta->tv_usec = time_adjtime % 1000000; 626 1.156 christos if (olddelta->tv_usec < 0) { 627 1.156 christos olddelta->tv_usec += 1000000; 628 1.156 christos olddelta->tv_sec--; 629 1.101 kardel } 630 1.157 christos mutex_spin_exit(&timecounter_lock); 631 1.101 kardel } 632 1.212 riastrad 633 1.101 kardel if (delta) { 634 1.156 christos mutex_spin_enter(&timecounter_lock); 635 1.212 riastrad /* 636 1.212 riastrad * XXX This should maybe just report failure to 637 1.212 riastrad * userland for nonsense deltas. 638 1.212 riastrad */ 639 1.212 riastrad if (delta->tv_sec > INT64_MAX/1000000 - 1) { 640 1.212 riastrad time_adjtime = INT64_MAX; 641 1.214 riastrad } else if (delta->tv_sec < INT64_MIN/1000000 + 1) { 642 1.214 riastrad time_adjtime = INT64_MIN; 643 1.212 riastrad } else { 644 1.214 riastrad time_adjtime = delta->tv_sec * 1000000 645 1.214 riastrad + MAX(-999999, MIN(999999, delta->tv_usec)); 646 1.212 riastrad } 647 1.101 kardel 648 1.143 ad if (time_adjtime) { 649 1.101 kardel /* We need to save the system time during shutdown */ 650 1.101 kardel time_adjusted |= 1; 651 1.143 ad } 652 1.143 ad mutex_spin_exit(&timecounter_lock); 653 1.101 kardel } 654 1.1 cgd } 655 1.1 cgd 656 1.1 cgd /* 657 1.207 thorpej * Interval timer support. 658 1.207 thorpej * 659 1.207 thorpej * The itimer_*() routines provide generic support for interval timers, 660 1.207 thorpej * both real (CLOCK_REALTIME, CLOCK_MONOTIME), and virtual (CLOCK_VIRTUAL, 661 1.207 thorpej * CLOCK_PROF). 662 1.207 thorpej * 663 1.207 thorpej * Real timers keep their deadline as an absolute time, and are fired 664 1.207 thorpej * by a callout. Virtual timers are kept as a linked-list of deltas, 665 1.207 thorpej * and are processed by hardclock(). 666 1.1 cgd * 667 1.207 thorpej * Because the real time timer callout may be delayed in real time due 668 1.207 thorpej * to interrupt processing on the system, it is possible for the real 669 1.207 thorpej * time timeout routine (itimer_callout()) run past after its deadline. 670 1.207 thorpej * It does not suffice, therefore, to reload the real timer .it_value 671 1.207 thorpej * from the timer's .it_interval. Rather, we compute the next deadline 672 1.207 thorpej * in absolute time based on the current time and the .it_interval value, 673 1.207 thorpej * and report any overruns. 674 1.1 cgd * 675 1.207 thorpej * Note that while the virtual timers are supported in a generic fashion 676 1.207 thorpej * here, they only (currently) make sense as per-process timers, and thus 677 1.207 thorpej * only really work for that case. 678 1.207 thorpej */ 679 1.63 thorpej 680 1.207 thorpej /* 681 1.207 thorpej * itimer_init: 682 1.207 thorpej * 683 1.207 thorpej * Initialize the common data for an interval timer. 684 1.207 thorpej */ 685 1.210 thorpej void 686 1.207 thorpej itimer_init(struct itimer * const it, const struct itimer_ops * const ops, 687 1.207 thorpej clockid_t const id, struct itlist * const itl) 688 1.63 thorpej { 689 1.92 cube 690 1.207 thorpej KASSERT(itimer_lock_held()); 691 1.207 thorpej KASSERT(ops != NULL); 692 1.207 thorpej 693 1.207 thorpej timespecclear(&it->it_time.it_value); 694 1.207 thorpej it->it_ops = ops; 695 1.207 thorpej it->it_clockid = id; 696 1.207 thorpej it->it_overruns = 0; 697 1.207 thorpej it->it_dying = false; 698 1.207 thorpej if (!CLOCK_VIRTUAL_P(id)) { 699 1.207 thorpej KASSERT(itl == NULL); 700 1.207 thorpej callout_init(&it->it_ch, CALLOUT_MPSAFE); 701 1.220 riastrad callout_setfunc(&it->it_ch, itimer_callout, it); 702 1.207 thorpej if (id == CLOCK_REALTIME && ops->ito_realtime_changed != NULL) { 703 1.207 thorpej LIST_INSERT_HEAD(&itimer_realtime_changed_notify, 704 1.207 thorpej it, it_rtchgq); 705 1.207 thorpej } 706 1.207 thorpej } else { 707 1.207 thorpej KASSERT(itl != NULL); 708 1.207 thorpej it->it_vlist = itl; 709 1.207 thorpej it->it_active = false; 710 1.207 thorpej } 711 1.92 cube } 712 1.92 cube 713 1.207 thorpej /* 714 1.210 thorpej * itimer_poison: 715 1.207 thorpej * 716 1.210 thorpej * Poison an interval timer, preventing it from being scheduled 717 1.210 thorpej * or processed, in preparation for freeing the timer. 718 1.207 thorpej */ 719 1.210 thorpej void 720 1.210 thorpej itimer_poison(struct itimer * const it) 721 1.92 cube { 722 1.105 ad 723 1.207 thorpej KASSERT(itimer_lock_held()); 724 1.63 thorpej 725 1.207 thorpej it->it_dying = true; 726 1.63 thorpej 727 1.207 thorpej /* 728 1.207 thorpej * For non-virtual timers, stop the callout, or wait for it to 729 1.207 thorpej * run if it has already fired. It cannot restart again after 730 1.207 thorpej * this point: the callout won't restart itself when dying, no 731 1.207 thorpej * other users holding the lock can restart it, and any other 732 1.207 thorpej * users waiting for callout_halt concurrently (itimer_settime) 733 1.207 thorpej * will restart from the top. 734 1.207 thorpej */ 735 1.207 thorpej if (!CLOCK_VIRTUAL_P(it->it_clockid)) { 736 1.207 thorpej callout_halt(&it->it_ch, &itimer_mutex); 737 1.207 thorpej if (it->it_clockid == CLOCK_REALTIME && 738 1.207 thorpej it->it_ops->ito_realtime_changed != NULL) { 739 1.207 thorpej LIST_REMOVE(it, it_rtchgq); 740 1.207 thorpej } 741 1.207 thorpej } 742 1.210 thorpej } 743 1.210 thorpej 744 1.210 thorpej /* 745 1.210 thorpej * itimer_fini: 746 1.210 thorpej * 747 1.210 thorpej * Release resources used by an interval timer. 748 1.210 thorpej * 749 1.210 thorpej * N.B. itimer_lock must be held on entry, and is released on exit. 750 1.210 thorpej */ 751 1.210 thorpej void 752 1.210 thorpej itimer_fini(struct itimer * const it) 753 1.210 thorpej { 754 1.63 thorpej 755 1.210 thorpej KASSERT(itimer_lock_held()); 756 1.142 ad 757 1.210 thorpej /* All done with the global state. */ 758 1.207 thorpej itimer_unlock(); 759 1.207 thorpej 760 1.207 thorpej /* Destroy the callout, if needed. */ 761 1.207 thorpej if (!CLOCK_VIRTUAL_P(it->it_clockid)) 762 1.207 thorpej callout_destroy(&it->it_ch); 763 1.207 thorpej } 764 1.207 thorpej 765 1.207 thorpej /* 766 1.207 thorpej * itimer_decr: 767 1.207 thorpej * 768 1.207 thorpej * Decrement an interval timer by a specified number of nanoseconds, 769 1.207 thorpej * which must be less than a second, i.e. < 1000000000. If the timer 770 1.207 thorpej * expires, then reload it. In this case, carry over (nsec - old value) 771 1.207 thorpej * to reduce the value reloaded into the timer so that the timer does 772 1.207 thorpej * not drift. This routine assumes that it is called in a context where 773 1.207 thorpej * the timers on which it is operating cannot change in value. 774 1.207 thorpej * 775 1.207 thorpej * Returns true if the timer has expired. 776 1.207 thorpej */ 777 1.207 thorpej static bool 778 1.207 thorpej itimer_decr(struct itimer *it, int nsec) 779 1.207 thorpej { 780 1.207 thorpej struct itimerspec *itp; 781 1.207 thorpej int error __diagused; 782 1.207 thorpej 783 1.207 thorpej KASSERT(itimer_lock_held()); 784 1.207 thorpej KASSERT(CLOCK_VIRTUAL_P(it->it_clockid)); 785 1.207 thorpej 786 1.207 thorpej itp = &it->it_time; 787 1.207 thorpej if (itp->it_value.tv_nsec < nsec) { 788 1.207 thorpej if (itp->it_value.tv_sec == 0) { 789 1.207 thorpej /* expired, and already in next interval */ 790 1.207 thorpej nsec -= itp->it_value.tv_nsec; 791 1.207 thorpej goto expire; 792 1.207 thorpej } 793 1.207 thorpej itp->it_value.tv_nsec += 1000000000; 794 1.207 thorpej itp->it_value.tv_sec--; 795 1.142 ad } 796 1.207 thorpej itp->it_value.tv_nsec -= nsec; 797 1.207 thorpej nsec = 0; 798 1.207 thorpej if (timespecisset(&itp->it_value)) 799 1.207 thorpej return false; 800 1.207 thorpej /* expired, exactly at end of interval */ 801 1.207 thorpej expire: 802 1.207 thorpej if (timespecisset(&itp->it_interval)) { 803 1.207 thorpej itp->it_value = itp->it_interval; 804 1.207 thorpej itp->it_value.tv_nsec -= nsec; 805 1.207 thorpej if (itp->it_value.tv_nsec < 0) { 806 1.207 thorpej itp->it_value.tv_nsec += 1000000000; 807 1.207 thorpej itp->it_value.tv_sec--; 808 1.63 thorpej } 809 1.207 thorpej error = itimer_settime(it); 810 1.207 thorpej KASSERT(error == 0); /* virtual, never fails */ 811 1.207 thorpej } else 812 1.207 thorpej itp->it_value.tv_nsec = 0; /* sec is already 0 */ 813 1.207 thorpej return true; 814 1.207 thorpej } 815 1.207 thorpej 816 1.207 thorpej /* 817 1.207 thorpej * itimer_arm_real: 818 1.207 thorpej * 819 1.207 thorpej * Arm a non-virtual timer. 820 1.207 thorpej */ 821 1.207 thorpej static void 822 1.207 thorpej itimer_arm_real(struct itimer * const it) 823 1.207 thorpej { 824 1.221 riastrad 825 1.219 thorpej KASSERT(!it->it_dying); 826 1.221 riastrad KASSERT(!CLOCK_VIRTUAL_P(it->it_clockid)); 827 1.221 riastrad KASSERT(!callout_pending(&it->it_ch)); 828 1.219 thorpej 829 1.207 thorpej /* 830 1.207 thorpej * Don't need to check tshzto() return value, here. 831 1.220 riastrad * callout_schedule() does it for us. 832 1.207 thorpej */ 833 1.220 riastrad callout_schedule(&it->it_ch, 834 1.207 thorpej (it->it_clockid == CLOCK_MONOTONIC 835 1.207 thorpej ? tshztoup(&it->it_time.it_value) 836 1.220 riastrad : tshzto(&it->it_time.it_value))); 837 1.63 thorpej } 838 1.63 thorpej 839 1.207 thorpej /* 840 1.207 thorpej * itimer_callout: 841 1.207 thorpej * 842 1.207 thorpej * Callout to expire a non-virtual timer. Queue it up for processing, 843 1.207 thorpej * and then reload, if it is configured to do so. 844 1.207 thorpej * 845 1.207 thorpej * N.B. A delay in processing this callout causes multiple 846 1.207 thorpej * SIGALRM calls to be compressed into one. 847 1.207 thorpej */ 848 1.207 thorpej static void 849 1.207 thorpej itimer_callout(void *arg) 850 1.15 thorpej { 851 1.207 thorpej struct timespec now, next; 852 1.207 thorpej struct itimer * const it = arg; 853 1.227 riastrad int overruns; 854 1.1 cgd 855 1.207 thorpej itimer_lock(); 856 1.207 thorpej (*it->it_ops->ito_fire)(it); 857 1.63 thorpej 858 1.207 thorpej if (!timespecisset(&it->it_time.it_interval)) { 859 1.207 thorpej timespecclear(&it->it_time.it_value); 860 1.207 thorpej itimer_unlock(); 861 1.207 thorpej return; 862 1.142 ad } 863 1.207 thorpej 864 1.207 thorpej if (it->it_clockid == CLOCK_MONOTONIC) { 865 1.207 thorpej getnanouptime(&now); 866 1.207 thorpej } else { 867 1.207 thorpej getnanotime(&now); 868 1.63 thorpej } 869 1.216 riastrad 870 1.227 riastrad /* 871 1.227 riastrad * Given the current itimer value and interval and the time 872 1.227 riastrad * now, compute the next itimer value and count overruns. 873 1.227 riastrad */ 874 1.227 riastrad itimer_transition(&it->it_time, &now, &next, &overruns); 875 1.227 riastrad it->it_time.it_value = next; 876 1.227 riastrad it->it_overruns += overruns; 877 1.63 thorpej 878 1.207 thorpej /* 879 1.207 thorpej * Reset the callout, if it's not going away. 880 1.207 thorpej */ 881 1.207 thorpej if (!it->it_dying) 882 1.207 thorpej itimer_arm_real(it); 883 1.207 thorpej itimer_unlock(); 884 1.63 thorpej } 885 1.63 thorpej 886 1.63 thorpej /* 887 1.207 thorpej * itimer_settime: 888 1.207 thorpej * 889 1.207 thorpej * Set up the given interval timer. The value in it->it_time.it_value 890 1.207 thorpej * is taken to be an absolute time for CLOCK_REALTIME/CLOCK_MONOTONIC 891 1.207 thorpej * timers and a relative time for CLOCK_VIRTUAL/CLOCK_PROF timers. 892 1.198 riastrad * 893 1.207 thorpej * If the callout had already fired but not yet run, fails with 894 1.207 thorpej * ERESTART -- caller must restart from the top to look up a timer. 895 1.224 riastrad * 896 1.224 riastrad * Caller is responsible for validating it->it_value and 897 1.224 riastrad * it->it_interval, e.g. with itimerfix or itimespecfix. 898 1.63 thorpej */ 899 1.198 riastrad int 900 1.207 thorpej itimer_settime(struct itimer *it) 901 1.63 thorpej { 902 1.207 thorpej struct itimer *itn, *pitn; 903 1.207 thorpej struct itlist *itl; 904 1.63 thorpej 905 1.207 thorpej KASSERT(itimer_lock_held()); 906 1.221 riastrad KASSERT(!it->it_dying); 907 1.224 riastrad KASSERT(it->it_time.it_value.tv_sec >= 0); 908 1.224 riastrad KASSERT(it->it_time.it_value.tv_nsec >= 0); 909 1.224 riastrad KASSERT(it->it_time.it_value.tv_nsec < 1000000000); 910 1.224 riastrad KASSERT(it->it_time.it_interval.tv_sec >= 0); 911 1.224 riastrad KASSERT(it->it_time.it_interval.tv_nsec >= 0); 912 1.224 riastrad KASSERT(it->it_time.it_interval.tv_nsec < 1000000000); 913 1.142 ad 914 1.207 thorpej if (!CLOCK_VIRTUAL_P(it->it_clockid)) { 915 1.198 riastrad /* 916 1.198 riastrad * Try to stop the callout. However, if it had already 917 1.198 riastrad * fired, we have to drop the lock to wait for it, so 918 1.198 riastrad * the world may have changed and pt may not be there 919 1.198 riastrad * any more. In that case, tell the caller to start 920 1.198 riastrad * over from the top. 921 1.198 riastrad */ 922 1.207 thorpej if (callout_halt(&it->it_ch, &itimer_mutex)) 923 1.198 riastrad return ERESTART; 924 1.221 riastrad KASSERT(!it->it_dying); 925 1.198 riastrad 926 1.207 thorpej /* Now we can touch it and start it up again. */ 927 1.207 thorpej if (timespecisset(&it->it_time.it_value)) 928 1.207 thorpej itimer_arm_real(it); 929 1.63 thorpej } else { 930 1.207 thorpej if (it->it_active) { 931 1.207 thorpej itn = LIST_NEXT(it, it_list); 932 1.207 thorpej LIST_REMOVE(it, it_list); 933 1.207 thorpej for ( ; itn; itn = LIST_NEXT(itn, it_list)) 934 1.207 thorpej timespecadd(&it->it_time.it_value, 935 1.207 thorpej &itn->it_time.it_value, 936 1.207 thorpej &itn->it_time.it_value); 937 1.207 thorpej } 938 1.207 thorpej if (timespecisset(&it->it_time.it_value)) { 939 1.207 thorpej itl = it->it_vlist; 940 1.207 thorpej for (itn = LIST_FIRST(itl), pitn = NULL; 941 1.207 thorpej itn && timespeccmp(&it->it_time.it_value, 942 1.207 thorpej &itn->it_time.it_value, >); 943 1.207 thorpej pitn = itn, itn = LIST_NEXT(itn, it_list)) 944 1.207 thorpej timespecsub(&it->it_time.it_value, 945 1.207 thorpej &itn->it_time.it_value, 946 1.207 thorpej &it->it_time.it_value); 947 1.207 thorpej 948 1.207 thorpej if (pitn) 949 1.207 thorpej LIST_INSERT_AFTER(pitn, it, it_list); 950 1.63 thorpej else 951 1.207 thorpej LIST_INSERT_HEAD(itl, it, it_list); 952 1.63 thorpej 953 1.207 thorpej for ( ; itn ; itn = LIST_NEXT(itn, it_list)) 954 1.207 thorpej timespecsub(&itn->it_time.it_value, 955 1.207 thorpej &it->it_time.it_value, 956 1.207 thorpej &itn->it_time.it_value); 957 1.63 thorpej 958 1.207 thorpej it->it_active = true; 959 1.207 thorpej } else { 960 1.207 thorpej it->it_active = false; 961 1.207 thorpej } 962 1.63 thorpej } 963 1.198 riastrad 964 1.198 riastrad /* Success! */ 965 1.198 riastrad return 0; 966 1.63 thorpej } 967 1.63 thorpej 968 1.207 thorpej /* 969 1.207 thorpej * itimer_gettime: 970 1.207 thorpej * 971 1.207 thorpej * Return the remaining time of an interval timer. 972 1.207 thorpej */ 973 1.63 thorpej void 974 1.207 thorpej itimer_gettime(const struct itimer *it, struct itimerspec *aits) 975 1.63 thorpej { 976 1.150 christos struct timespec now; 977 1.207 thorpej struct itimer *itn; 978 1.63 thorpej 979 1.207 thorpej KASSERT(itimer_lock_held()); 980 1.221 riastrad KASSERT(!it->it_dying); 981 1.142 ad 982 1.207 thorpej *aits = it->it_time; 983 1.207 thorpej if (!CLOCK_VIRTUAL_P(it->it_clockid)) { 984 1.1 cgd /* 985 1.12 mycroft * Convert from absolute to relative time in .it_value 986 1.63 thorpej * part of real time timer. If time for real time 987 1.63 thorpej * timer has passed return 0, else return difference 988 1.63 thorpej * between current time and time for the timer to go 989 1.63 thorpej * off. 990 1.1 cgd */ 991 1.150 christos if (timespecisset(&aits->it_value)) { 992 1.207 thorpej if (it->it_clockid == CLOCK_REALTIME) { 993 1.168 yamt getnanotime(&now); 994 1.168 yamt } else { /* CLOCK_MONOTONIC */ 995 1.168 yamt getnanouptime(&now); 996 1.168 yamt } 997 1.150 christos if (timespeccmp(&aits->it_value, &now, <)) 998 1.150 christos timespecclear(&aits->it_value); 999 1.101 kardel else 1000 1.150 christos timespecsub(&aits->it_value, &now, 1001 1.150 christos &aits->it_value); 1002 1.36 thorpej } 1003 1.207 thorpej } else if (it->it_active) { 1004 1.207 thorpej for (itn = LIST_FIRST(it->it_vlist); itn && itn != it; 1005 1.207 thorpej itn = LIST_NEXT(itn, it_list)) 1006 1.150 christos timespecadd(&aits->it_value, 1007 1.207 thorpej &itn->it_time.it_value, &aits->it_value); 1008 1.207 thorpej KASSERT(itn != NULL); /* it should be findable on the list */ 1009 1.1 cgd } else 1010 1.150 christos timespecclear(&aits->it_value); 1011 1.63 thorpej } 1012 1.63 thorpej 1013 1.207 thorpej /* 1014 1.207 thorpej * Per-process timer support. 1015 1.207 thorpej * 1016 1.207 thorpej * Both the BSD getitimer() family and the POSIX timer_*() family of 1017 1.207 thorpej * routines are supported. 1018 1.207 thorpej * 1019 1.207 thorpej * All timers are kept in an array pointed to by p_timers, which is 1020 1.207 thorpej * allocated on demand - many processes don't use timers at all. The 1021 1.207 thorpej * first four elements in this array are reserved for the BSD timers: 1022 1.207 thorpej * element 0 is ITIMER_REAL, element 1 is ITIMER_VIRTUAL, element 1023 1.207 thorpej * 2 is ITIMER_PROF, and element 3 is ITIMER_MONOTONIC. The rest may be 1024 1.207 thorpej * allocated by the timer_create() syscall. 1025 1.207 thorpej * 1026 1.207 thorpej * These timers are a "sub-class" of interval timer. 1027 1.207 thorpej */ 1028 1.207 thorpej 1029 1.207 thorpej /* 1030 1.207 thorpej * ptimer_free: 1031 1.207 thorpej * 1032 1.207 thorpej * Free the per-process timer at the specified index. 1033 1.207 thorpej */ 1034 1.207 thorpej static void 1035 1.207 thorpej ptimer_free(struct ptimers *pts, int index) 1036 1.207 thorpej { 1037 1.207 thorpej struct itimer *it; 1038 1.207 thorpej struct ptimer *pt; 1039 1.207 thorpej 1040 1.207 thorpej KASSERT(itimer_lock_held()); 1041 1.207 thorpej 1042 1.207 thorpej it = pts->pts_timers[index]; 1043 1.207 thorpej pt = container_of(it, struct ptimer, pt_itimer); 1044 1.207 thorpej pts->pts_timers[index] = NULL; 1045 1.210 thorpej itimer_poison(it); 1046 1.210 thorpej 1047 1.210 thorpej /* 1048 1.210 thorpej * Remove it from the queue to be signalled. Must be done 1049 1.210 thorpej * after itimer is poisoned, because we may have had to wait 1050 1.210 thorpej * for the callout to complete. 1051 1.210 thorpej */ 1052 1.210 thorpej if (pt->pt_queued) { 1053 1.210 thorpej TAILQ_REMOVE(&ptimer_queue, pt, pt_chain); 1054 1.210 thorpej pt->pt_queued = false; 1055 1.210 thorpej } 1056 1.210 thorpej 1057 1.207 thorpej itimer_fini(it); /* releases itimer_lock */ 1058 1.207 thorpej kmem_free(pt, sizeof(*pt)); 1059 1.207 thorpej } 1060 1.207 thorpej 1061 1.207 thorpej /* 1062 1.207 thorpej * ptimers_alloc: 1063 1.207 thorpej * 1064 1.207 thorpej * Allocate a ptimers for the specified process. 1065 1.207 thorpej */ 1066 1.207 thorpej static struct ptimers * 1067 1.207 thorpej ptimers_alloc(struct proc *p) 1068 1.207 thorpej { 1069 1.207 thorpej struct ptimers *pts; 1070 1.207 thorpej int i; 1071 1.207 thorpej 1072 1.207 thorpej pts = kmem_alloc(sizeof(*pts), KM_SLEEP); 1073 1.207 thorpej LIST_INIT(&pts->pts_virtual); 1074 1.207 thorpej LIST_INIT(&pts->pts_prof); 1075 1.207 thorpej for (i = 0; i < TIMER_MAX; i++) 1076 1.207 thorpej pts->pts_timers[i] = NULL; 1077 1.207 thorpej itimer_lock(); 1078 1.207 thorpej if (p->p_timers == NULL) { 1079 1.207 thorpej p->p_timers = pts; 1080 1.207 thorpej itimer_unlock(); 1081 1.207 thorpej return pts; 1082 1.207 thorpej } 1083 1.207 thorpej itimer_unlock(); 1084 1.207 thorpej kmem_free(pts, sizeof(*pts)); 1085 1.207 thorpej return p->p_timers; 1086 1.207 thorpej } 1087 1.207 thorpej 1088 1.207 thorpej /* 1089 1.207 thorpej * ptimers_free: 1090 1.207 thorpej * 1091 1.207 thorpej * Clean up the per-process timers. If "which" is set to TIMERS_ALL, 1092 1.207 thorpej * then clean up all timers and free all the data structures. If 1093 1.207 thorpej * "which" is set to TIMERS_POSIX, only clean up the timers allocated 1094 1.207 thorpej * by timer_create(), not the BSD setitimer() timers, and only free the 1095 1.207 thorpej * structure if none of those remain. 1096 1.207 thorpej * 1097 1.207 thorpej * This function is exported because it is needed in the exec and 1098 1.207 thorpej * exit code paths. 1099 1.207 thorpej */ 1100 1.207 thorpej void 1101 1.207 thorpej ptimers_free(struct proc *p, int which) 1102 1.207 thorpej { 1103 1.207 thorpej struct ptimers *pts; 1104 1.207 thorpej struct itimer *itn; 1105 1.207 thorpej struct timespec ts; 1106 1.207 thorpej int i; 1107 1.207 thorpej 1108 1.207 thorpej if (p->p_timers == NULL) 1109 1.207 thorpej return; 1110 1.207 thorpej 1111 1.207 thorpej pts = p->p_timers; 1112 1.207 thorpej itimer_lock(); 1113 1.207 thorpej if (which == TIMERS_ALL) { 1114 1.207 thorpej p->p_timers = NULL; 1115 1.207 thorpej i = 0; 1116 1.207 thorpej } else { 1117 1.207 thorpej timespecclear(&ts); 1118 1.207 thorpej for (itn = LIST_FIRST(&pts->pts_virtual); 1119 1.207 thorpej itn && itn != pts->pts_timers[ITIMER_VIRTUAL]; 1120 1.207 thorpej itn = LIST_NEXT(itn, it_list)) { 1121 1.207 thorpej KASSERT(itn->it_clockid == CLOCK_VIRTUAL); 1122 1.207 thorpej timespecadd(&ts, &itn->it_time.it_value, &ts); 1123 1.207 thorpej } 1124 1.207 thorpej LIST_FIRST(&pts->pts_virtual) = NULL; 1125 1.207 thorpej if (itn) { 1126 1.207 thorpej KASSERT(itn->it_clockid == CLOCK_VIRTUAL); 1127 1.207 thorpej timespecadd(&ts, &itn->it_time.it_value, 1128 1.207 thorpej &itn->it_time.it_value); 1129 1.207 thorpej LIST_INSERT_HEAD(&pts->pts_virtual, itn, it_list); 1130 1.207 thorpej } 1131 1.207 thorpej timespecclear(&ts); 1132 1.207 thorpej for (itn = LIST_FIRST(&pts->pts_prof); 1133 1.207 thorpej itn && itn != pts->pts_timers[ITIMER_PROF]; 1134 1.207 thorpej itn = LIST_NEXT(itn, it_list)) { 1135 1.207 thorpej KASSERT(itn->it_clockid == CLOCK_PROF); 1136 1.207 thorpej timespecadd(&ts, &itn->it_time.it_value, &ts); 1137 1.207 thorpej } 1138 1.207 thorpej LIST_FIRST(&pts->pts_prof) = NULL; 1139 1.207 thorpej if (itn) { 1140 1.207 thorpej KASSERT(itn->it_clockid == CLOCK_PROF); 1141 1.207 thorpej timespecadd(&ts, &itn->it_time.it_value, 1142 1.207 thorpej &itn->it_time.it_value); 1143 1.207 thorpej LIST_INSERT_HEAD(&pts->pts_prof, itn, it_list); 1144 1.207 thorpej } 1145 1.207 thorpej i = TIMER_MIN; 1146 1.207 thorpej } 1147 1.207 thorpej for ( ; i < TIMER_MAX; i++) { 1148 1.207 thorpej if (pts->pts_timers[i] != NULL) { 1149 1.207 thorpej /* Free the timer and release the lock. */ 1150 1.207 thorpej ptimer_free(pts, i); 1151 1.207 thorpej /* Reacquire the lock for the next one. */ 1152 1.207 thorpej itimer_lock(); 1153 1.207 thorpej } 1154 1.207 thorpej } 1155 1.207 thorpej if (pts->pts_timers[0] == NULL && pts->pts_timers[1] == NULL && 1156 1.207 thorpej pts->pts_timers[2] == NULL && pts->pts_timers[3] == NULL) { 1157 1.207 thorpej p->p_timers = NULL; 1158 1.207 thorpej itimer_unlock(); 1159 1.207 thorpej kmem_free(pts, sizeof(*pts)); 1160 1.207 thorpej } else 1161 1.207 thorpej itimer_unlock(); 1162 1.207 thorpej } 1163 1.207 thorpej 1164 1.207 thorpej /* 1165 1.207 thorpej * ptimer_fire: 1166 1.207 thorpej * 1167 1.207 thorpej * Fire a per-process timer. 1168 1.207 thorpej */ 1169 1.207 thorpej static void 1170 1.207 thorpej ptimer_fire(struct itimer *it) 1171 1.207 thorpej { 1172 1.207 thorpej struct ptimer *pt = container_of(it, struct ptimer, pt_itimer); 1173 1.207 thorpej 1174 1.207 thorpej KASSERT(itimer_lock_held()); 1175 1.207 thorpej 1176 1.207 thorpej /* 1177 1.207 thorpej * XXX Can overrun, but we don't do signal queueing yet, anyway. 1178 1.207 thorpej * XXX Relying on the clock interrupt is stupid. 1179 1.207 thorpej */ 1180 1.207 thorpej if (pt->pt_ev.sigev_notify != SIGEV_SIGNAL) { 1181 1.207 thorpej return; 1182 1.207 thorpej } 1183 1.210 thorpej 1184 1.210 thorpej if (!pt->pt_queued) { 1185 1.210 thorpej TAILQ_INSERT_TAIL(&ptimer_queue, pt, pt_chain); 1186 1.210 thorpej pt->pt_queued = true; 1187 1.210 thorpej softint_schedule(ptimer_sih); 1188 1.210 thorpej } 1189 1.207 thorpej } 1190 1.207 thorpej 1191 1.207 thorpej /* 1192 1.207 thorpej * Operations vector for per-process timers (BSD and POSIX). 1193 1.207 thorpej */ 1194 1.207 thorpej static const struct itimer_ops ptimer_itimer_ops = { 1195 1.210 thorpej .ito_fire = ptimer_fire, 1196 1.207 thorpej }; 1197 1.207 thorpej 1198 1.207 thorpej /* 1199 1.207 thorpej * sys_timer_create: 1200 1.207 thorpej * 1201 1.207 thorpej * System call to create a POSIX timer. 1202 1.207 thorpej */ 1203 1.207 thorpej int 1204 1.207 thorpej sys_timer_create(struct lwp *l, const struct sys_timer_create_args *uap, 1205 1.207 thorpej register_t *retval) 1206 1.207 thorpej { 1207 1.207 thorpej /* { 1208 1.207 thorpej syscallarg(clockid_t) clock_id; 1209 1.207 thorpej syscallarg(struct sigevent *) evp; 1210 1.207 thorpej syscallarg(timer_t *) timerid; 1211 1.207 thorpej } */ 1212 1.207 thorpej 1213 1.207 thorpej return timer_create1(SCARG(uap, timerid), SCARG(uap, clock_id), 1214 1.207 thorpej SCARG(uap, evp), copyin, l); 1215 1.207 thorpej } 1216 1.207 thorpej 1217 1.207 thorpej int 1218 1.207 thorpej timer_create1(timer_t *tid, clockid_t id, struct sigevent *evp, 1219 1.207 thorpej copyin_t fetch_event, struct lwp *l) 1220 1.207 thorpej { 1221 1.207 thorpej int error; 1222 1.207 thorpej timer_t timerid; 1223 1.207 thorpej struct itlist *itl; 1224 1.207 thorpej struct ptimers *pts; 1225 1.207 thorpej struct ptimer *pt; 1226 1.207 thorpej struct proc *p; 1227 1.63 thorpej 1228 1.207 thorpej p = l->l_proc; 1229 1.63 thorpej 1230 1.207 thorpej if ((u_int)id > CLOCK_MONOTONIC) 1231 1.217 riastrad return EINVAL; 1232 1.207 thorpej 1233 1.207 thorpej if ((pts = p->p_timers) == NULL) 1234 1.207 thorpej pts = ptimers_alloc(p); 1235 1.207 thorpej 1236 1.207 thorpej pt = kmem_zalloc(sizeof(*pt), KM_SLEEP); 1237 1.207 thorpej if (evp != NULL) { 1238 1.207 thorpej if (((error = 1239 1.207 thorpej (*fetch_event)(evp, &pt->pt_ev, sizeof(pt->pt_ev))) != 0) || 1240 1.207 thorpej ((pt->pt_ev.sigev_notify < SIGEV_NONE) || 1241 1.207 thorpej (pt->pt_ev.sigev_notify > SIGEV_SA)) || 1242 1.207 thorpej (pt->pt_ev.sigev_notify == SIGEV_SIGNAL && 1243 1.207 thorpej (pt->pt_ev.sigev_signo <= 0 || 1244 1.207 thorpej pt->pt_ev.sigev_signo >= NSIG))) { 1245 1.207 thorpej kmem_free(pt, sizeof(*pt)); 1246 1.207 thorpej return (error ? error : EINVAL); 1247 1.207 thorpej } 1248 1.207 thorpej } 1249 1.207 thorpej 1250 1.207 thorpej /* Find a free timer slot, skipping those reserved for setitimer(). */ 1251 1.207 thorpej itimer_lock(); 1252 1.207 thorpej for (timerid = TIMER_MIN; timerid < TIMER_MAX; timerid++) 1253 1.207 thorpej if (pts->pts_timers[timerid] == NULL) 1254 1.207 thorpej break; 1255 1.207 thorpej if (timerid == TIMER_MAX) { 1256 1.207 thorpej itimer_unlock(); 1257 1.207 thorpej kmem_free(pt, sizeof(*pt)); 1258 1.207 thorpej return EAGAIN; 1259 1.207 thorpej } 1260 1.207 thorpej if (evp == NULL) { 1261 1.207 thorpej pt->pt_ev.sigev_notify = SIGEV_SIGNAL; 1262 1.207 thorpej switch (id) { 1263 1.207 thorpej case CLOCK_REALTIME: 1264 1.207 thorpej case CLOCK_MONOTONIC: 1265 1.207 thorpej pt->pt_ev.sigev_signo = SIGALRM; 1266 1.207 thorpej break; 1267 1.207 thorpej case CLOCK_VIRTUAL: 1268 1.207 thorpej pt->pt_ev.sigev_signo = SIGVTALRM; 1269 1.207 thorpej break; 1270 1.207 thorpej case CLOCK_PROF: 1271 1.207 thorpej pt->pt_ev.sigev_signo = SIGPROF; 1272 1.207 thorpej break; 1273 1.207 thorpej } 1274 1.207 thorpej pt->pt_ev.sigev_value.sival_int = timerid; 1275 1.207 thorpej } 1276 1.207 thorpej 1277 1.207 thorpej switch (id) { 1278 1.207 thorpej case CLOCK_VIRTUAL: 1279 1.208 thorpej itl = &pts->pts_virtual; 1280 1.207 thorpej break; 1281 1.207 thorpej case CLOCK_PROF: 1282 1.208 thorpej itl = &pts->pts_prof; 1283 1.207 thorpej break; 1284 1.207 thorpej default: 1285 1.207 thorpej itl = NULL; 1286 1.207 thorpej } 1287 1.207 thorpej 1288 1.207 thorpej itimer_init(&pt->pt_itimer, &ptimer_itimer_ops, id, itl); 1289 1.207 thorpej pt->pt_proc = p; 1290 1.207 thorpej pt->pt_poverruns = 0; 1291 1.207 thorpej pt->pt_entry = timerid; 1292 1.210 thorpej pt->pt_queued = false; 1293 1.207 thorpej 1294 1.207 thorpej pts->pts_timers[timerid] = &pt->pt_itimer; 1295 1.207 thorpej itimer_unlock(); 1296 1.207 thorpej 1297 1.207 thorpej return copyout(&timerid, tid, sizeof(timerid)); 1298 1.207 thorpej } 1299 1.207 thorpej 1300 1.207 thorpej /* 1301 1.207 thorpej * sys_timer_delete: 1302 1.207 thorpej * 1303 1.207 thorpej * System call to delete a POSIX timer. 1304 1.207 thorpej */ 1305 1.207 thorpej int 1306 1.207 thorpej sys_timer_delete(struct lwp *l, const struct sys_timer_delete_args *uap, 1307 1.207 thorpej register_t *retval) 1308 1.207 thorpej { 1309 1.207 thorpej /* { 1310 1.207 thorpej syscallarg(timer_t) timerid; 1311 1.207 thorpej } */ 1312 1.207 thorpej struct proc *p = l->l_proc; 1313 1.207 thorpej timer_t timerid; 1314 1.207 thorpej struct ptimers *pts; 1315 1.207 thorpej struct itimer *it, *itn; 1316 1.207 thorpej 1317 1.207 thorpej timerid = SCARG(uap, timerid); 1318 1.207 thorpej pts = p->p_timers; 1319 1.217 riastrad 1320 1.207 thorpej if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX) 1321 1.217 riastrad return EINVAL; 1322 1.207 thorpej 1323 1.207 thorpej itimer_lock(); 1324 1.207 thorpej if ((it = pts->pts_timers[timerid]) == NULL) { 1325 1.207 thorpej itimer_unlock(); 1326 1.217 riastrad return EINVAL; 1327 1.207 thorpej } 1328 1.207 thorpej 1329 1.207 thorpej if (CLOCK_VIRTUAL_P(it->it_clockid)) { 1330 1.207 thorpej if (it->it_active) { 1331 1.207 thorpej itn = LIST_NEXT(it, it_list); 1332 1.207 thorpej LIST_REMOVE(it, it_list); 1333 1.207 thorpej for ( ; itn; itn = LIST_NEXT(itn, it_list)) 1334 1.207 thorpej timespecadd(&it->it_time.it_value, 1335 1.207 thorpej &itn->it_time.it_value, 1336 1.207 thorpej &itn->it_time.it_value); 1337 1.207 thorpej it->it_active = false; 1338 1.207 thorpej } 1339 1.207 thorpej } 1340 1.207 thorpej 1341 1.207 thorpej /* Free the timer and release the lock. */ 1342 1.207 thorpej ptimer_free(pts, timerid); 1343 1.207 thorpej 1344 1.217 riastrad return 0; 1345 1.207 thorpej } 1346 1.207 thorpej 1347 1.207 thorpej /* 1348 1.207 thorpej * sys___timer_settime50: 1349 1.207 thorpej * 1350 1.207 thorpej * System call to set/arm a POSIX timer. 1351 1.207 thorpej */ 1352 1.63 thorpej int 1353 1.156 christos sys___timer_settime50(struct lwp *l, 1354 1.156 christos const struct sys___timer_settime50_args *uap, 1355 1.140 yamt register_t *retval) 1356 1.63 thorpej { 1357 1.135 dsl /* { 1358 1.63 thorpej syscallarg(timer_t) timerid; 1359 1.63 thorpej syscallarg(int) flags; 1360 1.63 thorpej syscallarg(const struct itimerspec *) value; 1361 1.63 thorpej syscallarg(struct itimerspec *) ovalue; 1362 1.135 dsl } */ 1363 1.92 cube int error; 1364 1.92 cube struct itimerspec value, ovalue, *ovp = NULL; 1365 1.92 cube 1366 1.92 cube if ((error = copyin(SCARG(uap, value), &value, 1367 1.92 cube sizeof(struct itimerspec))) != 0) 1368 1.217 riastrad return error; 1369 1.92 cube 1370 1.92 cube if (SCARG(uap, ovalue)) 1371 1.92 cube ovp = &ovalue; 1372 1.92 cube 1373 1.92 cube if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp, 1374 1.92 cube SCARG(uap, flags), l->l_proc)) != 0) 1375 1.92 cube return error; 1376 1.92 cube 1377 1.92 cube if (ovp) 1378 1.92 cube return copyout(&ovalue, SCARG(uap, ovalue), 1379 1.92 cube sizeof(struct itimerspec)); 1380 1.92 cube return 0; 1381 1.92 cube } 1382 1.92 cube 1383 1.92 cube int 1384 1.92 cube dotimer_settime(int timerid, struct itimerspec *value, 1385 1.92 cube struct itimerspec *ovalue, int flags, struct proc *p) 1386 1.92 cube { 1387 1.150 christos struct timespec now; 1388 1.223 riastrad struct itimerspec val; 1389 1.142 ad struct ptimers *pts; 1390 1.207 thorpej struct itimer *it; 1391 1.160 christos int error; 1392 1.63 thorpej 1393 1.142 ad pts = p->p_timers; 1394 1.63 thorpej 1395 1.142 ad if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX) 1396 1.142 ad return EINVAL; 1397 1.150 christos val = *value; 1398 1.222 riastrad if (itimespecfix(&val.it_value) != 0 || 1399 1.222 riastrad itimespecfix(&val.it_interval) != 0) 1400 1.222 riastrad return EINVAL; 1401 1.63 thorpej 1402 1.207 thorpej itimer_lock(); 1403 1.207 thorpej restart: 1404 1.207 thorpej if ((it = pts->pts_timers[timerid]) == NULL) { 1405 1.207 thorpej itimer_unlock(); 1406 1.150 christos return EINVAL; 1407 1.142 ad } 1408 1.142 ad 1409 1.223 riastrad if (ovalue) 1410 1.223 riastrad itimer_gettime(it, ovalue); 1411 1.207 thorpej it->it_time = val; 1412 1.63 thorpej 1413 1.67 nathanw /* 1414 1.67 nathanw * If we've been passed a relative time for a realtime timer, 1415 1.67 nathanw * convert it to absolute; if an absolute time for a virtual 1416 1.67 nathanw * timer, convert it to relative and make sure we don't set it 1417 1.67 nathanw * to zero, which would cancel the timer, or let it go 1418 1.67 nathanw * negative, which would confuse the comparison tests. 1419 1.67 nathanw */ 1420 1.207 thorpej if (timespecisset(&it->it_time.it_value)) { 1421 1.207 thorpej if (!CLOCK_VIRTUAL_P(it->it_clockid)) { 1422 1.101 kardel if ((flags & TIMER_ABSTIME) == 0) { 1423 1.207 thorpej if (it->it_clockid == CLOCK_REALTIME) { 1424 1.168 yamt getnanotime(&now); 1425 1.168 yamt } else { /* CLOCK_MONOTONIC */ 1426 1.168 yamt getnanouptime(&now); 1427 1.168 yamt } 1428 1.207 thorpej timespecadd(&it->it_time.it_value, &now, 1429 1.207 thorpej &it->it_time.it_value); 1430 1.101 kardel } 1431 1.67 nathanw } else { 1432 1.92 cube if ((flags & TIMER_ABSTIME) != 0) { 1433 1.150 christos getnanotime(&now); 1434 1.207 thorpej timespecsub(&it->it_time.it_value, &now, 1435 1.207 thorpej &it->it_time.it_value); 1436 1.207 thorpej if (!timespecisset(&it->it_time.it_value) || 1437 1.207 thorpej it->it_time.it_value.tv_sec < 0) { 1438 1.207 thorpej it->it_time.it_value.tv_sec = 0; 1439 1.207 thorpej it->it_time.it_value.tv_nsec = 1; 1440 1.67 nathanw } 1441 1.67 nathanw } 1442 1.67 nathanw } 1443 1.67 nathanw } 1444 1.67 nathanw 1445 1.207 thorpej error = itimer_settime(it); 1446 1.198 riastrad if (error == ERESTART) { 1447 1.207 thorpej KASSERT(!CLOCK_VIRTUAL_P(it->it_clockid)); 1448 1.198 riastrad goto restart; 1449 1.198 riastrad } 1450 1.198 riastrad KASSERT(error == 0); 1451 1.207 thorpej itimer_unlock(); 1452 1.63 thorpej 1453 1.217 riastrad return 0; 1454 1.63 thorpej } 1455 1.63 thorpej 1456 1.207 thorpej /* 1457 1.207 thorpej * sys___timer_gettime50: 1458 1.207 thorpej * 1459 1.207 thorpej * System call to return the time remaining until a POSIX timer fires. 1460 1.207 thorpej */ 1461 1.63 thorpej int 1462 1.156 christos sys___timer_gettime50(struct lwp *l, 1463 1.156 christos const struct sys___timer_gettime50_args *uap, register_t *retval) 1464 1.63 thorpej { 1465 1.135 dsl /* { 1466 1.63 thorpej syscallarg(timer_t) timerid; 1467 1.63 thorpej syscallarg(struct itimerspec *) value; 1468 1.135 dsl } */ 1469 1.63 thorpej struct itimerspec its; 1470 1.92 cube int error; 1471 1.92 cube 1472 1.92 cube if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc, 1473 1.92 cube &its)) != 0) 1474 1.92 cube return error; 1475 1.92 cube 1476 1.92 cube return copyout(&its, SCARG(uap, value), sizeof(its)); 1477 1.92 cube } 1478 1.92 cube 1479 1.92 cube int 1480 1.92 cube dotimer_gettime(int timerid, struct proc *p, struct itimerspec *its) 1481 1.92 cube { 1482 1.207 thorpej struct itimer *it; 1483 1.142 ad struct ptimers *pts; 1484 1.63 thorpej 1485 1.142 ad pts = p->p_timers; 1486 1.142 ad if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX) 1487 1.217 riastrad return EINVAL; 1488 1.207 thorpej itimer_lock(); 1489 1.207 thorpej if ((it = pts->pts_timers[timerid]) == NULL) { 1490 1.207 thorpej itimer_unlock(); 1491 1.217 riastrad return EINVAL; 1492 1.142 ad } 1493 1.207 thorpej itimer_gettime(it, its); 1494 1.207 thorpej itimer_unlock(); 1495 1.63 thorpej 1496 1.92 cube return 0; 1497 1.63 thorpej } 1498 1.63 thorpej 1499 1.63 thorpej /* 1500 1.207 thorpej * sys_timer_getoverrun: 1501 1.207 thorpej * 1502 1.207 thorpej * System call to return the number of times a POSIX timer has 1503 1.207 thorpej * expired while a notification was already pending. The counter 1504 1.207 thorpej * is reset when a timer expires and a notification can be posted. 1505 1.63 thorpej */ 1506 1.63 thorpej int 1507 1.140 yamt sys_timer_getoverrun(struct lwp *l, const struct sys_timer_getoverrun_args *uap, 1508 1.140 yamt register_t *retval) 1509 1.63 thorpej { 1510 1.135 dsl /* { 1511 1.63 thorpej syscallarg(timer_t) timerid; 1512 1.135 dsl } */ 1513 1.63 thorpej struct proc *p = l->l_proc; 1514 1.142 ad struct ptimers *pts; 1515 1.63 thorpej int timerid; 1516 1.207 thorpej struct itimer *it; 1517 1.63 thorpej struct ptimer *pt; 1518 1.63 thorpej 1519 1.63 thorpej timerid = SCARG(uap, timerid); 1520 1.63 thorpej 1521 1.142 ad pts = p->p_timers; 1522 1.142 ad if (pts == NULL || timerid < 2 || timerid >= TIMER_MAX) 1523 1.217 riastrad return EINVAL; 1524 1.207 thorpej itimer_lock(); 1525 1.207 thorpej if ((it = pts->pts_timers[timerid]) == NULL) { 1526 1.207 thorpej itimer_unlock(); 1527 1.217 riastrad return EINVAL; 1528 1.142 ad } 1529 1.207 thorpej pt = container_of(it, struct ptimer, pt_itimer); 1530 1.63 thorpej *retval = pt->pt_poverruns; 1531 1.187 christos if (*retval >= DELAYTIMER_MAX) 1532 1.187 christos *retval = DELAYTIMER_MAX; 1533 1.207 thorpej itimer_unlock(); 1534 1.63 thorpej 1535 1.217 riastrad return 0; 1536 1.63 thorpej } 1537 1.63 thorpej 1538 1.63 thorpej /* 1539 1.207 thorpej * sys___getitimer50: 1540 1.207 thorpej * 1541 1.207 thorpej * System call to get the time remaining before a BSD timer fires. 1542 1.63 thorpej */ 1543 1.63 thorpej int 1544 1.156 christos sys___getitimer50(struct lwp *l, const struct sys___getitimer50_args *uap, 1545 1.140 yamt register_t *retval) 1546 1.63 thorpej { 1547 1.135 dsl /* { 1548 1.63 thorpej syscallarg(int) which; 1549 1.63 thorpej syscallarg(struct itimerval *) itv; 1550 1.135 dsl } */ 1551 1.63 thorpej struct proc *p = l->l_proc; 1552 1.63 thorpej struct itimerval aitv; 1553 1.91 cube int error; 1554 1.91 cube 1555 1.191 maxv memset(&aitv, 0, sizeof(aitv)); 1556 1.91 cube error = dogetitimer(p, SCARG(uap, which), &aitv); 1557 1.91 cube if (error) 1558 1.91 cube return error; 1559 1.217 riastrad return copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval)); 1560 1.91 cube } 1561 1.63 thorpej 1562 1.91 cube int 1563 1.91 cube dogetitimer(struct proc *p, int which, struct itimerval *itvp) 1564 1.91 cube { 1565 1.142 ad struct ptimers *pts; 1566 1.207 thorpej struct itimer *it; 1567 1.150 christos struct itimerspec its; 1568 1.63 thorpej 1569 1.170 christos if ((u_int)which > ITIMER_MONOTONIC) 1570 1.217 riastrad return EINVAL; 1571 1.63 thorpej 1572 1.207 thorpej itimer_lock(); 1573 1.142 ad pts = p->p_timers; 1574 1.207 thorpej if (pts == NULL || (it = pts->pts_timers[which]) == NULL) { 1575 1.91 cube timerclear(&itvp->it_value); 1576 1.91 cube timerclear(&itvp->it_interval); 1577 1.150 christos } else { 1578 1.207 thorpej itimer_gettime(it, &its); 1579 1.151 christos TIMESPEC_TO_TIMEVAL(&itvp->it_value, &its.it_value); 1580 1.151 christos TIMESPEC_TO_TIMEVAL(&itvp->it_interval, &its.it_interval); 1581 1.150 christos } 1582 1.207 thorpej itimer_unlock(); 1583 1.63 thorpej 1584 1.91 cube return 0; 1585 1.1 cgd } 1586 1.1 cgd 1587 1.207 thorpej /* 1588 1.207 thorpej * sys___setitimer50: 1589 1.207 thorpej * 1590 1.207 thorpej * System call to set/arm a BSD timer. 1591 1.207 thorpej */ 1592 1.3 andrew int 1593 1.156 christos sys___setitimer50(struct lwp *l, const struct sys___setitimer50_args *uap, 1594 1.140 yamt register_t *retval) 1595 1.15 thorpej { 1596 1.135 dsl /* { 1597 1.30 mycroft syscallarg(int) which; 1598 1.24 cgd syscallarg(const struct itimerval *) itv; 1599 1.11 cgd syscallarg(struct itimerval *) oitv; 1600 1.135 dsl } */ 1601 1.63 thorpej struct proc *p = l->l_proc; 1602 1.30 mycroft int which = SCARG(uap, which); 1603 1.156 christos struct sys___getitimer50_args getargs; 1604 1.91 cube const struct itimerval *itvp; 1605 1.1 cgd struct itimerval aitv; 1606 1.91 cube int error; 1607 1.1 cgd 1608 1.11 cgd itvp = SCARG(uap, itv); 1609 1.63 thorpej if (itvp && 1610 1.174 dholland (error = copyin(itvp, &aitv, sizeof(struct itimerval))) != 0) 1611 1.217 riastrad return error; 1612 1.21 cgd if (SCARG(uap, oitv) != NULL) { 1613 1.30 mycroft SCARG(&getargs, which) = which; 1614 1.21 cgd SCARG(&getargs, itv) = SCARG(uap, oitv); 1615 1.156 christos if ((error = sys___getitimer50(l, &getargs, retval)) != 0) 1616 1.217 riastrad return error; 1617 1.21 cgd } 1618 1.1 cgd if (itvp == 0) 1619 1.217 riastrad return 0; 1620 1.91 cube 1621 1.91 cube return dosetitimer(p, which, &aitv); 1622 1.91 cube } 1623 1.91 cube 1624 1.91 cube int 1625 1.91 cube dosetitimer(struct proc *p, int which, struct itimerval *itvp) 1626 1.91 cube { 1627 1.150 christos struct timespec now; 1628 1.142 ad struct ptimers *pts; 1629 1.207 thorpej struct ptimer *spare; 1630 1.207 thorpej struct itimer *it; 1631 1.207 thorpej struct itlist *itl; 1632 1.198 riastrad int error; 1633 1.91 cube 1634 1.211 simonb if ((u_int)which > ITIMER_MONOTONIC) 1635 1.217 riastrad return EINVAL; 1636 1.91 cube if (itimerfix(&itvp->it_value) || itimerfix(&itvp->it_interval)) 1637 1.217 riastrad return EINVAL; 1638 1.63 thorpej 1639 1.63 thorpej /* 1640 1.63 thorpej * Don't bother allocating data structures if the process just 1641 1.63 thorpej * wants to clear the timer. 1642 1.63 thorpej */ 1643 1.142 ad spare = NULL; 1644 1.142 ad pts = p->p_timers; 1645 1.142 ad retry: 1646 1.142 ad if (!timerisset(&itvp->it_value) && (pts == NULL || 1647 1.142 ad pts->pts_timers[which] == NULL)) 1648 1.217 riastrad return 0; 1649 1.142 ad if (pts == NULL) 1650 1.207 thorpej pts = ptimers_alloc(p); 1651 1.207 thorpej itimer_lock(); 1652 1.207 thorpej restart: 1653 1.207 thorpej it = pts->pts_timers[which]; 1654 1.207 thorpej if (it == NULL) { 1655 1.207 thorpej struct ptimer *pt; 1656 1.207 thorpej 1657 1.142 ad if (spare == NULL) { 1658 1.207 thorpej itimer_unlock(); 1659 1.207 thorpej spare = kmem_zalloc(sizeof(*spare), KM_SLEEP); 1660 1.142 ad goto retry; 1661 1.142 ad } 1662 1.142 ad pt = spare; 1663 1.142 ad spare = NULL; 1664 1.207 thorpej 1665 1.207 thorpej it = &pt->pt_itimer; 1666 1.63 thorpej pt->pt_ev.sigev_notify = SIGEV_SIGNAL; 1667 1.76 christos pt->pt_ev.sigev_value.sival_int = which; 1668 1.149 christos 1669 1.63 thorpej switch (which) { 1670 1.63 thorpej case ITIMER_REAL: 1671 1.170 christos case ITIMER_MONOTONIC: 1672 1.207 thorpej itl = NULL; 1673 1.63 thorpej pt->pt_ev.sigev_signo = SIGALRM; 1674 1.63 thorpej break; 1675 1.63 thorpej case ITIMER_VIRTUAL: 1676 1.208 thorpej itl = &pts->pts_virtual; 1677 1.63 thorpej pt->pt_ev.sigev_signo = SIGVTALRM; 1678 1.63 thorpej break; 1679 1.63 thorpej case ITIMER_PROF: 1680 1.208 thorpej itl = &pts->pts_prof; 1681 1.63 thorpej pt->pt_ev.sigev_signo = SIGPROF; 1682 1.63 thorpej break; 1683 1.209 christos default: 1684 1.209 christos panic("%s: can't happen %d", __func__, which); 1685 1.1 cgd } 1686 1.207 thorpej itimer_init(it, &ptimer_itimer_ops, which, itl); 1687 1.207 thorpej pt->pt_proc = p; 1688 1.207 thorpej pt->pt_entry = which; 1689 1.207 thorpej 1690 1.207 thorpej pts->pts_timers[which] = it; 1691 1.142 ad } 1692 1.63 thorpej 1693 1.207 thorpej TIMEVAL_TO_TIMESPEC(&itvp->it_value, &it->it_time.it_value); 1694 1.207 thorpej TIMEVAL_TO_TIMESPEC(&itvp->it_interval, &it->it_time.it_interval); 1695 1.150 christos 1696 1.215 riastrad error = 0; 1697 1.207 thorpej if (timespecisset(&it->it_time.it_value)) { 1698 1.67 nathanw /* Convert to absolute time */ 1699 1.101 kardel /* XXX need to wrap in splclock for timecounters case? */ 1700 1.170 christos switch (which) { 1701 1.170 christos case ITIMER_REAL: 1702 1.170 christos getnanotime(&now); 1703 1.215 riastrad if (!timespecaddok(&it->it_time.it_value, &now)) { 1704 1.215 riastrad error = EINVAL; 1705 1.215 riastrad goto out; 1706 1.215 riastrad } 1707 1.207 thorpej timespecadd(&it->it_time.it_value, &now, 1708 1.207 thorpej &it->it_time.it_value); 1709 1.170 christos break; 1710 1.170 christos case ITIMER_MONOTONIC: 1711 1.170 christos getnanouptime(&now); 1712 1.215 riastrad if (!timespecaddok(&it->it_time.it_value, &now)) { 1713 1.215 riastrad error = EINVAL; 1714 1.215 riastrad goto out; 1715 1.215 riastrad } 1716 1.207 thorpej timespecadd(&it->it_time.it_value, &now, 1717 1.207 thorpej &it->it_time.it_value); 1718 1.170 christos break; 1719 1.170 christos default: 1720 1.170 christos break; 1721 1.170 christos } 1722 1.67 nathanw } 1723 1.215 riastrad 1724 1.207 thorpej error = itimer_settime(it); 1725 1.198 riastrad if (error == ERESTART) { 1726 1.207 thorpej KASSERT(!CLOCK_VIRTUAL_P(it->it_clockid)); 1727 1.198 riastrad goto restart; 1728 1.198 riastrad } 1729 1.198 riastrad KASSERT(error == 0); 1730 1.215 riastrad out: 1731 1.207 thorpej itimer_unlock(); 1732 1.142 ad if (spare != NULL) 1733 1.207 thorpej kmem_free(spare, sizeof(*spare)); 1734 1.63 thorpej 1735 1.215 riastrad return error; 1736 1.1 cgd } 1737 1.1 cgd 1738 1.1 cgd /* 1739 1.207 thorpej * ptimer_tick: 1740 1.207 thorpej * 1741 1.207 thorpej * Called from hardclock() to decrement per-process virtual timers. 1742 1.1 cgd */ 1743 1.3 andrew void 1744 1.207 thorpej ptimer_tick(lwp_t *l, bool user) 1745 1.6 cgd { 1746 1.63 thorpej struct ptimers *pts; 1747 1.207 thorpej struct itimer *it; 1748 1.142 ad proc_t *p; 1749 1.142 ad 1750 1.142 ad p = l->l_proc; 1751 1.142 ad if (p->p_timers == NULL) 1752 1.142 ad return; 1753 1.142 ad 1754 1.207 thorpej itimer_lock(); 1755 1.142 ad if ((pts = l->l_proc->p_timers) != NULL) { 1756 1.63 thorpej /* 1757 1.142 ad * Run current process's virtual and profile time, as needed. 1758 1.63 thorpej */ 1759 1.207 thorpej if (user && (it = LIST_FIRST(&pts->pts_virtual)) != NULL) 1760 1.207 thorpej if (itimer_decr(it, tick * 1000)) 1761 1.207 thorpej (*it->it_ops->ito_fire)(it); 1762 1.207 thorpej if ((it = LIST_FIRST(&pts->pts_prof)) != NULL) 1763 1.207 thorpej if (itimer_decr(it, tick * 1000)) 1764 1.207 thorpej (*it->it_ops->ito_fire)(it); 1765 1.142 ad } 1766 1.207 thorpej itimer_unlock(); 1767 1.142 ad } 1768 1.142 ad 1769 1.207 thorpej /* 1770 1.207 thorpej * ptimer_intr: 1771 1.207 thorpej * 1772 1.207 thorpej * Software interrupt handler for processing per-process 1773 1.207 thorpej * timer expiration. 1774 1.207 thorpej */ 1775 1.142 ad static void 1776 1.207 thorpej ptimer_intr(void *cookie) 1777 1.142 ad { 1778 1.142 ad ksiginfo_t ksi; 1779 1.207 thorpej struct itimer *it; 1780 1.142 ad struct ptimer *pt; 1781 1.142 ad proc_t *p; 1782 1.217 riastrad 1783 1.205 ad mutex_enter(&proc_lock); 1784 1.207 thorpej itimer_lock(); 1785 1.210 thorpej while ((pt = TAILQ_FIRST(&ptimer_queue)) != NULL) { 1786 1.210 thorpej it = &pt->pt_itimer; 1787 1.142 ad 1788 1.210 thorpej TAILQ_REMOVE(&ptimer_queue, pt, pt_chain); 1789 1.210 thorpej KASSERT(pt->pt_queued); 1790 1.210 thorpej pt->pt_queued = false; 1791 1.207 thorpej 1792 1.207 thorpej p = pt->pt_proc; 1793 1.207 thorpej if (p->p_timers == NULL) { 1794 1.154 wrstuden /* Process is dying. */ 1795 1.142 ad continue; 1796 1.154 wrstuden } 1797 1.172 rmind if (pt->pt_ev.sigev_notify != SIGEV_SIGNAL) { 1798 1.142 ad continue; 1799 1.142 ad } 1800 1.142 ad if (sigismember(&p->p_sigpend.sp_set, pt->pt_ev.sigev_signo)) { 1801 1.207 thorpej it->it_overruns++; 1802 1.142 ad continue; 1803 1.64 nathanw } 1804 1.142 ad 1805 1.142 ad KSI_INIT(&ksi); 1806 1.142 ad ksi.ksi_signo = pt->pt_ev.sigev_signo; 1807 1.142 ad ksi.ksi_code = SI_TIMER; 1808 1.142 ad ksi.ksi_value = pt->pt_ev.sigev_value; 1809 1.207 thorpej pt->pt_poverruns = it->it_overruns; 1810 1.207 thorpej it->it_overruns = 0; 1811 1.207 thorpej itimer_unlock(); 1812 1.142 ad kpsignal(p, &ksi, NULL); 1813 1.207 thorpej itimer_lock(); 1814 1.63 thorpej } 1815 1.207 thorpej itimer_unlock(); 1816 1.205 ad mutex_exit(&proc_lock); 1817 1.63 thorpej } 1818