kern_time.c revision 1.121
1/* $NetBSD: kern_time.c,v 1.121 2007/05/13 10:58:51 dsl Exp $ */ 2 3/*- 4 * Copyright (c) 2000, 2004, 2005 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christopher G. Demetriou. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39/* 40 * Copyright (c) 1982, 1986, 1989, 1993 41 * The Regents of the University of California. All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. Neither the name of the University nor the names of its contributors 52 * may be used to endorse or promote products derived from this software 53 * without specific prior written permission. 54 * 55 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 58 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 65 * SUCH DAMAGE. 66 * 67 * @(#)kern_time.c 8.4 (Berkeley) 5/26/95 68 */ 69 70#include <sys/cdefs.h> 71__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.121 2007/05/13 10:58:51 dsl Exp $"); 72 73#include <sys/param.h> 74#include <sys/resourcevar.h> 75#include <sys/kernel.h> 76#include <sys/systm.h> 77#include <sys/proc.h> 78#include <sys/vnode.h> 79#include <sys/signalvar.h> 80#include <sys/syslog.h> 81#ifdef __HAVE_TIMECOUNTER 82#include <sys/timetc.h> 83#else /* !__HAVE_TIMECOUNTER */ 84#include <sys/timevar.h> 85#endif /* !__HAVE_TIMECOUNTER */ 86#include <sys/kauth.h> 87 88#include <sys/mount.h> 89#include <sys/syscallargs.h> 90 91#include <uvm/uvm_extern.h> 92 93#include <machine/cpu.h> 94 95POOL_INIT(ptimer_pool, sizeof(struct ptimer), 0, 0, 0, "ptimerpl", 96 &pool_allocator_nointr, IPL_NONE); 97POOL_INIT(ptimers_pool, sizeof(struct ptimers), 0, 0, 0, "ptimerspl", 98 &pool_allocator_nointr, IPL_NONE); 99 100#ifdef __HAVE_TIMECOUNTER 101static int itimespecfix(struct timespec *); /* XXX move itimerfix to timespecs */ 102#endif /* __HAVE_TIMECOUNTER */ 103 104/* Time of day and interval timer support. 105 * 106 * These routines provide the kernel entry points to get and set 107 * the time-of-day and per-process interval timers. Subroutines 108 * here provide support for adding and subtracting timeval structures 109 * and decrementing interval timers, optionally reloading the interval 110 * timers when they expire. 111 */ 112 113/* This function is used by clock_settime and settimeofday */ 114int 115settime(struct proc *p, struct timespec *ts) 116{ 117 struct timeval delta, tv; 118#ifdef __HAVE_TIMECOUNTER 119 struct timeval now; 120 struct timespec ts1; 121#endif /* !__HAVE_TIMECOUNTER */ 122 struct cpu_info *ci; 123 int s1, s2; 124 125 /* 126 * Don't allow the time to be set forward so far it will wrap 127 * and become negative, thus allowing an attacker to bypass 128 * the next check below. The cutoff is 1 year before rollover 129 * occurs, so even if the attacker uses adjtime(2) to move 130 * the time past the cutoff, it will take a very long time 131 * to get to the wrap point. 132 * 133 * XXX: we check against INT_MAX since on 64-bit 134 * platforms, sizeof(int) != sizeof(long) and 135 * time_t is 32 bits even when atv.tv_sec is 64 bits. 136 */ 137 if (ts->tv_sec > INT_MAX - 365*24*60*60) { 138 struct proc *pp; 139 140 mutex_enter(&proclist_lock); 141 pp = p->p_pptr; 142 mutex_enter(&pp->p_mutex); 143 log(LOG_WARNING, "pid %d (%s) " 144 "invoked by uid %d ppid %d (%s) " 145 "tried to set clock forward to %ld\n", 146 p->p_pid, p->p_comm, kauth_cred_geteuid(pp->p_cred), 147 pp->p_pid, pp->p_comm, (long)ts->tv_sec); 148 mutex_exit(&pp->p_mutex); 149 mutex_exit(&proclist_lock); 150 return (EPERM); 151 } 152 TIMESPEC_TO_TIMEVAL(&tv, ts); 153 154 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 155 s1 = splsoftclock(); 156 s2 = splclock(); 157#ifdef __HAVE_TIMECOUNTER 158 microtime(&now); 159 timersub(&tv, &now, &delta); 160#else /* !__HAVE_TIMECOUNTER */ 161 timersub(&tv, &time, &delta); 162#endif /* !__HAVE_TIMECOUNTER */ 163 if ((delta.tv_sec < 0 || delta.tv_usec < 0) && 164 kauth_authorize_system(p->p_cred, KAUTH_SYSTEM_TIME, 165 KAUTH_REQ_SYSTEM_TIME_BACKWARDS, NULL, NULL, NULL)) { 166 splx(s1); 167 return (EPERM); 168 } 169#ifdef notyet 170 if ((delta.tv_sec < 86400) && securelevel > 0) { /* XXX elad - notyet */ 171 splx(s1); 172 return (EPERM); 173 } 174#endif 175 176#ifdef __HAVE_TIMECOUNTER 177 TIMEVAL_TO_TIMESPEC(&tv, &ts1); 178 tc_setclock(&ts1); 179#else /* !__HAVE_TIMECOUNTER */ 180 time = tv; 181#endif /* !__HAVE_TIMECOUNTER */ 182 183 splx(s2); 184 185 timeradd(&boottime, &delta, &boottime); 186 187 /* 188 * XXXSMP 189 * This is wrong. We should traverse a list of all 190 * CPUs and add the delta to the runtime of those 191 * CPUs which have a process on them. 192 */ 193 ci = curcpu(); 194 timeradd(&ci->ci_schedstate.spc_runtime, &delta, 195 &ci->ci_schedstate.spc_runtime); 196 splx(s1); 197 resettodr(); 198 return (0); 199} 200 201/* ARGSUSED */ 202int 203sys_clock_gettime(struct lwp *l, void *v, register_t *retval) 204{ 205 struct sys_clock_gettime_args /* { 206 syscallarg(clockid_t) clock_id; 207 syscallarg(struct timespec *) tp; 208 } */ *uap = v; 209 clockid_t clock_id; 210 struct timespec ats; 211 212 clock_id = SCARG(uap, clock_id); 213 switch (clock_id) { 214 case CLOCK_REALTIME: 215 nanotime(&ats); 216 break; 217 case CLOCK_MONOTONIC: 218 nanouptime(&ats); 219 break; 220 default: 221 return (EINVAL); 222 } 223 224 return copyout(&ats, SCARG(uap, tp), sizeof(ats)); 225} 226 227/* ARGSUSED */ 228int 229sys_clock_settime(struct lwp *l, void *v, register_t *retval) 230{ 231 struct sys_clock_settime_args /* { 232 syscallarg(clockid_t) clock_id; 233 syscallarg(const struct timespec *) tp; 234 } */ *uap = v; 235 int error; 236 237 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME, 238 KAUTH_REQ_SYSTEM_TIME_SYSTEM, NULL, NULL, NULL)) != 0) 239 return (error); 240 241 return clock_settime1(l->l_proc, SCARG(uap, clock_id), SCARG(uap, tp)); 242} 243 244 245int 246clock_settime1(struct proc *p, clockid_t clock_id, const struct timespec *tp) 247{ 248 struct timespec ats; 249 int error; 250 251 if ((error = copyin(tp, &ats, sizeof(ats))) != 0) 252 return (error); 253 254 switch (clock_id) { 255 case CLOCK_REALTIME: 256 if ((error = settime(p, &ats)) != 0) 257 return (error); 258 break; 259 case CLOCK_MONOTONIC: 260 return (EINVAL); /* read-only clock */ 261 default: 262 return (EINVAL); 263 } 264 265 return 0; 266} 267 268int 269sys_clock_getres(struct lwp *l, void *v, register_t *retval) 270{ 271 struct sys_clock_getres_args /* { 272 syscallarg(clockid_t) clock_id; 273 syscallarg(struct timespec *) tp; 274 } */ *uap = v; 275 clockid_t clock_id; 276 struct timespec ts; 277 int error = 0; 278 279 clock_id = SCARG(uap, clock_id); 280 switch (clock_id) { 281 case CLOCK_REALTIME: 282 case CLOCK_MONOTONIC: 283 ts.tv_sec = 0; 284 if (tc_getfrequency() > 1000000000) 285 ts.tv_nsec = 1; 286 else 287 ts.tv_nsec = 1000000000 / tc_getfrequency(); 288 break; 289 default: 290 return (EINVAL); 291 } 292 293 if (SCARG(uap, tp)) 294 error = copyout(&ts, SCARG(uap, tp), sizeof(ts)); 295 296 return error; 297} 298 299/* ARGSUSED */ 300int 301sys_nanosleep(struct lwp *l, void *v, register_t *retval) 302{ 303 struct sys_nanosleep_args/* { 304 syscallarg(struct timespec *) rqtp; 305 syscallarg(struct timespec *) rmtp; 306 } */ *uap = v; 307 struct timespec rmt, rqt; 308 int error, error1; 309 310 error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec)); 311 if (error) 312 return (error); 313 314 error = nanosleep1(l, &rqt, SCARG(uap, rmtp) ? &rmt : NULL); 315 if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR)) 316 return error; 317 318 error1 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt)); 319 return error1 ? error1 : error; 320} 321 322int 323nanosleep1(struct lwp *l, struct timespec *rqt, struct timespec *rmt) 324{ 325#ifdef __HAVE_TIMECOUNTER 326 int error, timo; 327 328 if (itimespecfix(rqt)) 329 return (EINVAL); 330 331 timo = tstohz(rqt); 332 /* 333 * Avoid inadvertantly sleeping forever 334 */ 335 if (timo == 0) 336 timo = 1; 337 338 getnanouptime(rmt); 339 340 error = kpause("nanoslp", true, timo, NULL); 341 if (error == ERESTART) 342 error = EINTR; 343 if (error == EWOULDBLOCK) 344 error = 0; 345 346 if (rmt!= NULL) { 347 struct timespec rmtend; 348 349 getnanouptime(&rmtend); 350 351 timespecsub(&rmtend, rmt, rmt); 352 timespecsub(rqt, rmt, rmt); 353 if (rmt->tv_sec < 0) 354 timespecclear(rmt); 355 } 356 357 return error; 358#else /* !__HAVE_TIMECOUNTER */ 359 struct timeval atv, utv; 360 int error, s, timo; 361 362 TIMESPEC_TO_TIMEVAL(&atv, rqt); 363 if (itimerfix(&atv)) 364 return (EINVAL); 365 366 s = splclock(); 367 timeradd(&atv,&time,&atv); 368 timo = hzto(&atv); 369 /* 370 * Avoid inadvertantly sleeping forever 371 */ 372 if (timo == 0) 373 timo = 1; 374 splx(s); 375 376 error = kpause("nanoslp", true, timo, NULL); 377 if (error == ERESTART) 378 error = EINTR; 379 if (error == EWOULDBLOCK) 380 error = 0; 381 382 if (rmt != NULL) { 383 s = splclock(); 384 utv = time; 385 splx(s); 386 387 timersub(&atv, &utv, &utv); 388 if (utv.tv_sec < 0) 389 timerclear(&utv); 390 391 TIMEVAL_TO_TIMESPEC(&utv, rmt); 392 } 393 394 return error; 395#endif /* !__HAVE_TIMECOUNTER */ 396} 397 398/* ARGSUSED */ 399int 400sys_gettimeofday(struct lwp *l, void *v, register_t *retval) 401{ 402 struct sys_gettimeofday_args /* { 403 syscallarg(struct timeval *) tp; 404 syscallarg(void *) tzp; really "struct timezone *" 405 } */ *uap = v; 406 struct timeval atv; 407 int error = 0; 408 struct timezone tzfake; 409 410 if (SCARG(uap, tp)) { 411 microtime(&atv); 412 error = copyout(&atv, SCARG(uap, tp), sizeof(atv)); 413 if (error) 414 return (error); 415 } 416 if (SCARG(uap, tzp)) { 417 /* 418 * NetBSD has no kernel notion of time zone, so we just 419 * fake up a timezone struct and return it if demanded. 420 */ 421 tzfake.tz_minuteswest = 0; 422 tzfake.tz_dsttime = 0; 423 error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake)); 424 } 425 return (error); 426} 427 428/* ARGSUSED */ 429int 430sys_settimeofday(struct lwp *l, void *v, register_t *retval) 431{ 432 struct sys_settimeofday_args /* { 433 syscallarg(const struct timeval *) tv; 434 syscallarg(const void *) tzp; really "const struct timezone *" 435 } */ *uap = v; 436 437 return settimeofday1(SCARG(uap, tv), true, SCARG(uap, tzp), l, true); 438} 439 440int 441settimeofday1(const struct timeval *utv, bool userspace, 442 const void *utzp, struct lwp *l, bool check_kauth) 443{ 444 struct timeval atv; 445 struct timespec ts; 446 int error; 447 448 /* Verify all parameters before changing time. */ 449 450 if (check_kauth) { 451 error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME, 452 KAUTH_REQ_SYSTEM_TIME_SYSTEM, NULL, NULL, NULL); 453 if (error != 0) 454 return (error); 455 } 456 457 /* 458 * NetBSD has no kernel notion of time zone, and only an 459 * obsolete program would try to set it, so we log a warning. 460 */ 461 if (utzp) 462 log(LOG_WARNING, "pid %d attempted to set the " 463 "(obsolete) kernel time zone\n", l->l_proc->p_pid); 464 465 if (utv == NULL) 466 return 0; 467 468 if (userspace) { 469 if ((error = copyin(utv, &atv, sizeof(atv))) != 0) 470 return error; 471 utv = &atv; 472 } 473 474 TIMEVAL_TO_TIMESPEC(utv, &ts); 475 return settime(l->l_proc, &ts); 476} 477 478#ifndef __HAVE_TIMECOUNTER 479int tickdelta; /* current clock skew, us. per tick */ 480long timedelta; /* unapplied time correction, us. */ 481long bigadj = 1000000; /* use 10x skew above bigadj us. */ 482#endif 483 484int time_adjusted; /* set if an adjustment is made */ 485 486/* ARGSUSED */ 487int 488sys_adjtime(struct lwp *l, void *v, register_t *retval) 489{ 490 struct sys_adjtime_args /* { 491 syscallarg(const struct timeval *) delta; 492 syscallarg(struct timeval *) olddelta; 493 } */ *uap = v; 494 int error; 495 496 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME, 497 KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL, NULL)) != 0) 498 return (error); 499 500 return adjtime1(SCARG(uap, delta), SCARG(uap, olddelta), l->l_proc); 501} 502 503int 504adjtime1(const struct timeval *delta, struct timeval *olddelta, struct proc *p) 505{ 506 struct timeval atv; 507 int error = 0; 508 509#ifdef __HAVE_TIMECOUNTER 510 extern int64_t time_adjtime; /* in kern_ntptime.c */ 511#else /* !__HAVE_TIMECOUNTER */ 512 long ndelta, ntickdelta, odelta; 513 int s; 514#endif /* !__HAVE_TIMECOUNTER */ 515 516#ifdef __HAVE_TIMECOUNTER 517 if (olddelta) { 518 atv.tv_sec = time_adjtime / 1000000; 519 atv.tv_usec = time_adjtime % 1000000; 520 if (atv.tv_usec < 0) { 521 atv.tv_usec += 1000000; 522 atv.tv_sec--; 523 } 524 error = copyout(&atv, olddelta, sizeof(struct timeval)); 525 if (error) 526 return (error); 527 } 528 529 if (delta) { 530 error = copyin(delta, &atv, sizeof(struct timeval)); 531 if (error) 532 return (error); 533 534 time_adjtime = (int64_t)atv.tv_sec * 1000000 + 535 atv.tv_usec; 536 537 if (time_adjtime) 538 /* We need to save the system time during shutdown */ 539 time_adjusted |= 1; 540 } 541#else /* !__HAVE_TIMECOUNTER */ 542 error = copyin(delta, &atv, sizeof(struct timeval)); 543 if (error) 544 return (error); 545 546 /* 547 * Compute the total correction and the rate at which to apply it. 548 * Round the adjustment down to a whole multiple of the per-tick 549 * delta, so that after some number of incremental changes in 550 * hardclock(), tickdelta will become zero, lest the correction 551 * overshoot and start taking us away from the desired final time. 552 */ 553 ndelta = atv.tv_sec * 1000000 + atv.tv_usec; 554 if (ndelta > bigadj || ndelta < -bigadj) 555 ntickdelta = 10 * tickadj; 556 else 557 ntickdelta = tickadj; 558 if (ndelta % ntickdelta) 559 ndelta = ndelta / ntickdelta * ntickdelta; 560 561 /* 562 * To make hardclock()'s job easier, make the per-tick delta negative 563 * if we want time to run slower; then hardclock can simply compute 564 * tick + tickdelta, and subtract tickdelta from timedelta. 565 */ 566 if (ndelta < 0) 567 ntickdelta = -ntickdelta; 568 if (ndelta != 0) 569 /* We need to save the system clock time during shutdown */ 570 time_adjusted |= 1; 571 s = splclock(); 572 odelta = timedelta; 573 timedelta = ndelta; 574 tickdelta = ntickdelta; 575 splx(s); 576 577 if (olddelta) { 578 atv.tv_sec = odelta / 1000000; 579 atv.tv_usec = odelta % 1000000; 580 error = copyout(&atv, olddelta, sizeof(struct timeval)); 581 } 582#endif /* __HAVE_TIMECOUNTER */ 583 584 return error; 585} 586 587/* 588 * Interval timer support. Both the BSD getitimer() family and the POSIX 589 * timer_*() family of routines are supported. 590 * 591 * All timers are kept in an array pointed to by p_timers, which is 592 * allocated on demand - many processes don't use timers at all. The 593 * first three elements in this array are reserved for the BSD timers: 594 * element 0 is ITIMER_REAL, element 1 is ITIMER_VIRTUAL, and element 595 * 2 is ITIMER_PROF. The rest may be allocated by the timer_create() 596 * syscall. 597 * 598 * Realtime timers are kept in the ptimer structure as an absolute 599 * time; virtual time timers are kept as a linked list of deltas. 600 * Virtual time timers are processed in the hardclock() routine of 601 * kern_clock.c. The real time timer is processed by a callout 602 * routine, called from the softclock() routine. Since a callout may 603 * be delayed in real time due to interrupt processing in the system, 604 * it is possible for the real time timeout routine (realtimeexpire, 605 * given below), to be delayed in real time past when it is supposed 606 * to occur. It does not suffice, therefore, to reload the real timer 607 * .it_value from the real time timers .it_interval. Rather, we 608 * compute the next time in absolute time the timer should go off. */ 609 610/* Allocate a POSIX realtime timer. */ 611int 612sys_timer_create(struct lwp *l, void *v, register_t *retval) 613{ 614 struct sys_timer_create_args /* { 615 syscallarg(clockid_t) clock_id; 616 syscallarg(struct sigevent *) evp; 617 syscallarg(timer_t *) timerid; 618 } */ *uap = v; 619 620 return timer_create1(SCARG(uap, timerid), SCARG(uap, clock_id), 621 SCARG(uap, evp), copyin, l); 622} 623 624int 625timer_create1(timer_t *tid, clockid_t id, struct sigevent *evp, 626 copyin_t fetch_event, struct lwp *l) 627{ 628 int error; 629 timer_t timerid; 630 struct ptimer *pt; 631 struct proc *p; 632 633 p = l->l_proc; 634 635 if (id < CLOCK_REALTIME || 636 id > CLOCK_PROF) 637 return (EINVAL); 638 639 if (p->p_timers == NULL) 640 timers_alloc(p); 641 642 /* Find a free timer slot, skipping those reserved for setitimer(). */ 643 for (timerid = 3; timerid < TIMER_MAX; timerid++) 644 if (p->p_timers->pts_timers[timerid] == NULL) 645 break; 646 647 if (timerid == TIMER_MAX) 648 return EAGAIN; 649 650 pt = pool_get(&ptimer_pool, PR_WAITOK); 651 if (evp) { 652 if (((error = 653 (*fetch_event)(evp, &pt->pt_ev, sizeof(pt->pt_ev))) != 0) || 654 ((pt->pt_ev.sigev_notify < SIGEV_NONE) || 655 (pt->pt_ev.sigev_notify > SIGEV_SA))) { 656 pool_put(&ptimer_pool, pt); 657 return (error ? error : EINVAL); 658 } 659 } else { 660 pt->pt_ev.sigev_notify = SIGEV_SIGNAL; 661 switch (id) { 662 case CLOCK_REALTIME: 663 pt->pt_ev.sigev_signo = SIGALRM; 664 break; 665 case CLOCK_VIRTUAL: 666 pt->pt_ev.sigev_signo = SIGVTALRM; 667 break; 668 case CLOCK_PROF: 669 pt->pt_ev.sigev_signo = SIGPROF; 670 break; 671 } 672 pt->pt_ev.sigev_value.sival_int = timerid; 673 } 674 pt->pt_info.ksi_signo = pt->pt_ev.sigev_signo; 675 pt->pt_info.ksi_errno = 0; 676 pt->pt_info.ksi_code = 0; 677 pt->pt_info.ksi_pid = p->p_pid; 678 pt->pt_info.ksi_uid = kauth_cred_getuid(l->l_cred); 679 pt->pt_info.ksi_sigval = pt->pt_ev.sigev_value; 680 681 pt->pt_type = id; 682 pt->pt_proc = p; 683 pt->pt_overruns = 0; 684 pt->pt_poverruns = 0; 685 pt->pt_entry = timerid; 686 timerclear(&pt->pt_time.it_value); 687 if (id == CLOCK_REALTIME) 688 callout_init(&pt->pt_ch); 689 else 690 pt->pt_active = 0; 691 692 p->p_timers->pts_timers[timerid] = pt; 693 694 return copyout(&timerid, tid, sizeof(timerid)); 695} 696 697/* Delete a POSIX realtime timer */ 698int 699sys_timer_delete(struct lwp *l, void *v, register_t *retval) 700{ 701 struct sys_timer_delete_args /* { 702 syscallarg(timer_t) timerid; 703 } */ *uap = v; 704 struct proc *p = l->l_proc; 705 timer_t timerid; 706 struct ptimer *pt, *ptn; 707 int s; 708 709 timerid = SCARG(uap, timerid); 710 711 if ((p->p_timers == NULL) || 712 (timerid < 2) || (timerid >= TIMER_MAX) || 713 ((pt = p->p_timers->pts_timers[timerid]) == NULL)) 714 return (EINVAL); 715 716 if (pt->pt_type == CLOCK_REALTIME) 717 callout_stop(&pt->pt_ch); 718 else if (pt->pt_active) { 719 s = splclock(); 720 ptn = LIST_NEXT(pt, pt_list); 721 LIST_REMOVE(pt, pt_list); 722 for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list)) 723 timeradd(&pt->pt_time.it_value, &ptn->pt_time.it_value, 724 &ptn->pt_time.it_value); 725 splx(s); 726 } 727 728 p->p_timers->pts_timers[timerid] = NULL; 729 pool_put(&ptimer_pool, pt); 730 731 return (0); 732} 733 734/* 735 * Set up the given timer. The value in pt->pt_time.it_value is taken 736 * to be an absolute time for CLOCK_REALTIME timers and a relative 737 * time for virtual timers. 738 * Must be called at splclock(). 739 */ 740void 741timer_settime(struct ptimer *pt) 742{ 743 struct ptimer *ptn, *pptn; 744 struct ptlist *ptl; 745 746 if (pt->pt_type == CLOCK_REALTIME) { 747 callout_stop(&pt->pt_ch); 748 if (timerisset(&pt->pt_time.it_value)) { 749 /* 750 * Don't need to check hzto() return value, here. 751 * callout_reset() does it for us. 752 */ 753 callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value), 754 realtimerexpire, pt); 755 } 756 } else { 757 if (pt->pt_active) { 758 ptn = LIST_NEXT(pt, pt_list); 759 LIST_REMOVE(pt, pt_list); 760 for ( ; ptn; ptn = LIST_NEXT(ptn, pt_list)) 761 timeradd(&pt->pt_time.it_value, 762 &ptn->pt_time.it_value, 763 &ptn->pt_time.it_value); 764 } 765 if (timerisset(&pt->pt_time.it_value)) { 766 if (pt->pt_type == CLOCK_VIRTUAL) 767 ptl = &pt->pt_proc->p_timers->pts_virtual; 768 else 769 ptl = &pt->pt_proc->p_timers->pts_prof; 770 771 for (ptn = LIST_FIRST(ptl), pptn = NULL; 772 ptn && timercmp(&pt->pt_time.it_value, 773 &ptn->pt_time.it_value, >); 774 pptn = ptn, ptn = LIST_NEXT(ptn, pt_list)) 775 timersub(&pt->pt_time.it_value, 776 &ptn->pt_time.it_value, 777 &pt->pt_time.it_value); 778 779 if (pptn) 780 LIST_INSERT_AFTER(pptn, pt, pt_list); 781 else 782 LIST_INSERT_HEAD(ptl, pt, pt_list); 783 784 for ( ; ptn ; ptn = LIST_NEXT(ptn, pt_list)) 785 timersub(&ptn->pt_time.it_value, 786 &pt->pt_time.it_value, 787 &ptn->pt_time.it_value); 788 789 pt->pt_active = 1; 790 } else 791 pt->pt_active = 0; 792 } 793} 794 795void 796timer_gettime(struct ptimer *pt, struct itimerval *aitv) 797{ 798#ifdef __HAVE_TIMECOUNTER 799 struct timeval now; 800#endif 801 struct ptimer *ptn; 802 803 *aitv = pt->pt_time; 804 if (pt->pt_type == CLOCK_REALTIME) { 805 /* 806 * Convert from absolute to relative time in .it_value 807 * part of real time timer. If time for real time 808 * timer has passed return 0, else return difference 809 * between current time and time for the timer to go 810 * off. 811 */ 812 if (timerisset(&aitv->it_value)) { 813#ifdef __HAVE_TIMECOUNTER 814 getmicrotime(&now); 815 if (timercmp(&aitv->it_value, &now, <)) 816 timerclear(&aitv->it_value); 817 else 818 timersub(&aitv->it_value, &now, 819 &aitv->it_value); 820#else /* !__HAVE_TIMECOUNTER */ 821 if (timercmp(&aitv->it_value, &time, <)) 822 timerclear(&aitv->it_value); 823 else 824 timersub(&aitv->it_value, &time, 825 &aitv->it_value); 826#endif /* !__HAVE_TIMECOUNTER */ 827 } 828 } else if (pt->pt_active) { 829 if (pt->pt_type == CLOCK_VIRTUAL) 830 ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_virtual); 831 else 832 ptn = LIST_FIRST(&pt->pt_proc->p_timers->pts_prof); 833 for ( ; ptn && ptn != pt; ptn = LIST_NEXT(ptn, pt_list)) 834 timeradd(&aitv->it_value, 835 &ptn->pt_time.it_value, &aitv->it_value); 836 KASSERT(ptn != NULL); /* pt should be findable on the list */ 837 } else 838 timerclear(&aitv->it_value); 839} 840 841 842 843/* Set and arm a POSIX realtime timer */ 844int 845sys_timer_settime(struct lwp *l, void *v, register_t *retval) 846{ 847 struct sys_timer_settime_args /* { 848 syscallarg(timer_t) timerid; 849 syscallarg(int) flags; 850 syscallarg(const struct itimerspec *) value; 851 syscallarg(struct itimerspec *) ovalue; 852 } */ *uap = v; 853 int error; 854 struct itimerspec value, ovalue, *ovp = NULL; 855 856 if ((error = copyin(SCARG(uap, value), &value, 857 sizeof(struct itimerspec))) != 0) 858 return (error); 859 860 if (SCARG(uap, ovalue)) 861 ovp = &ovalue; 862 863 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp, 864 SCARG(uap, flags), l->l_proc)) != 0) 865 return error; 866 867 if (ovp) 868 return copyout(&ovalue, SCARG(uap, ovalue), 869 sizeof(struct itimerspec)); 870 return 0; 871} 872 873int 874dotimer_settime(int timerid, struct itimerspec *value, 875 struct itimerspec *ovalue, int flags, struct proc *p) 876{ 877#ifdef __HAVE_TIMECOUNTER 878 struct timeval now; 879#endif 880 struct itimerval val, oval; 881 struct ptimer *pt; 882 int s; 883 884 if ((p->p_timers == NULL) || 885 (timerid < 2) || (timerid >= TIMER_MAX) || 886 ((pt = p->p_timers->pts_timers[timerid]) == NULL)) 887 return (EINVAL); 888 889 TIMESPEC_TO_TIMEVAL(&val.it_value, &value->it_value); 890 TIMESPEC_TO_TIMEVAL(&val.it_interval, &value->it_interval); 891 if (itimerfix(&val.it_value) || itimerfix(&val.it_interval)) 892 return (EINVAL); 893 894 oval = pt->pt_time; 895 pt->pt_time = val; 896 897 s = splclock(); 898 /* 899 * If we've been passed a relative time for a realtime timer, 900 * convert it to absolute; if an absolute time for a virtual 901 * timer, convert it to relative and make sure we don't set it 902 * to zero, which would cancel the timer, or let it go 903 * negative, which would confuse the comparison tests. 904 */ 905 if (timerisset(&pt->pt_time.it_value)) { 906 if (pt->pt_type == CLOCK_REALTIME) { 907#ifdef __HAVE_TIMECOUNTER 908 if ((flags & TIMER_ABSTIME) == 0) { 909 getmicrotime(&now); 910 timeradd(&pt->pt_time.it_value, &now, 911 &pt->pt_time.it_value); 912 } 913#else /* !__HAVE_TIMECOUNTER */ 914 if ((flags & TIMER_ABSTIME) == 0) 915 timeradd(&pt->pt_time.it_value, &time, 916 &pt->pt_time.it_value); 917#endif /* !__HAVE_TIMECOUNTER */ 918 } else { 919 if ((flags & TIMER_ABSTIME) != 0) { 920#ifdef __HAVE_TIMECOUNTER 921 getmicrotime(&now); 922 timersub(&pt->pt_time.it_value, &now, 923 &pt->pt_time.it_value); 924#else /* !__HAVE_TIMECOUNTER */ 925 timersub(&pt->pt_time.it_value, &time, 926 &pt->pt_time.it_value); 927#endif /* !__HAVE_TIMECOUNTER */ 928 if (!timerisset(&pt->pt_time.it_value) || 929 pt->pt_time.it_value.tv_sec < 0) { 930 pt->pt_time.it_value.tv_sec = 0; 931 pt->pt_time.it_value.tv_usec = 1; 932 } 933 } 934 } 935 } 936 937 timer_settime(pt); 938 splx(s); 939 940 if (ovalue) { 941 TIMEVAL_TO_TIMESPEC(&oval.it_value, &ovalue->it_value); 942 TIMEVAL_TO_TIMESPEC(&oval.it_interval, &ovalue->it_interval); 943 } 944 945 return (0); 946} 947 948/* Return the time remaining until a POSIX timer fires. */ 949int 950sys_timer_gettime(struct lwp *l, void *v, register_t *retval) 951{ 952 struct sys_timer_gettime_args /* { 953 syscallarg(timer_t) timerid; 954 syscallarg(struct itimerspec *) value; 955 } */ *uap = v; 956 struct itimerspec its; 957 int error; 958 959 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc, 960 &its)) != 0) 961 return error; 962 963 return copyout(&its, SCARG(uap, value), sizeof(its)); 964} 965 966int 967dotimer_gettime(int timerid, struct proc *p, struct itimerspec *its) 968{ 969 int s; 970 struct ptimer *pt; 971 struct itimerval aitv; 972 973 if ((p->p_timers == NULL) || 974 (timerid < 2) || (timerid >= TIMER_MAX) || 975 ((pt = p->p_timers->pts_timers[timerid]) == NULL)) 976 return (EINVAL); 977 978 s = splclock(); 979 timer_gettime(pt, &aitv); 980 splx(s); 981 982 TIMEVAL_TO_TIMESPEC(&aitv.it_interval, &its->it_interval); 983 TIMEVAL_TO_TIMESPEC(&aitv.it_value, &its->it_value); 984 985 return 0; 986} 987 988/* 989 * Return the count of the number of times a periodic timer expired 990 * while a notification was already pending. The counter is reset when 991 * a timer expires and a notification can be posted. 992 */ 993int 994sys_timer_getoverrun(struct lwp *l, void *v, register_t *retval) 995{ 996 struct sys_timer_getoverrun_args /* { 997 syscallarg(timer_t) timerid; 998 } */ *uap = v; 999 struct proc *p = l->l_proc; 1000 int timerid; 1001 struct ptimer *pt; 1002 1003 timerid = SCARG(uap, timerid); 1004 1005 if ((p->p_timers == NULL) || 1006 (timerid < 2) || (timerid >= TIMER_MAX) || 1007 ((pt = p->p_timers->pts_timers[timerid]) == NULL)) 1008 return (EINVAL); 1009 1010 *retval = pt->pt_poverruns; 1011 1012 return (0); 1013} 1014 1015/* 1016 * Real interval timer expired: 1017 * send process whose timer expired an alarm signal. 1018 * If time is not set up to reload, then just return. 1019 * Else compute next time timer should go off which is > current time. 1020 * This is where delay in processing this timeout causes multiple 1021 * SIGALRM calls to be compressed into one. 1022 */ 1023void 1024realtimerexpire(void *arg) 1025{ 1026#ifdef __HAVE_TIMECOUNTER 1027 struct timeval now; 1028#endif 1029 struct ptimer *pt; 1030 int s; 1031 1032 pt = (struct ptimer *)arg; 1033 1034 itimerfire(pt); 1035 1036 if (!timerisset(&pt->pt_time.it_interval)) { 1037 timerclear(&pt->pt_time.it_value); 1038 return; 1039 } 1040#ifdef __HAVE_TIMECOUNTER 1041 for (;;) { 1042 s = splclock(); /* XXX need spl now? */ 1043 timeradd(&pt->pt_time.it_value, 1044 &pt->pt_time.it_interval, &pt->pt_time.it_value); 1045 getmicrotime(&now); 1046 if (timercmp(&pt->pt_time.it_value, &now, >)) { 1047 /* 1048 * Don't need to check hzto() return value, here. 1049 * callout_reset() does it for us. 1050 */ 1051 callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value), 1052 realtimerexpire, pt); 1053 splx(s); 1054 return; 1055 } 1056 splx(s); 1057 pt->pt_overruns++; 1058 } 1059#else /* !__HAVE_TIMECOUNTER */ 1060 for (;;) { 1061 s = splclock(); 1062 timeradd(&pt->pt_time.it_value, 1063 &pt->pt_time.it_interval, &pt->pt_time.it_value); 1064 if (timercmp(&pt->pt_time.it_value, &time, >)) { 1065 /* 1066 * Don't need to check hzto() return value, here. 1067 * callout_reset() does it for us. 1068 */ 1069 callout_reset(&pt->pt_ch, hzto(&pt->pt_time.it_value), 1070 realtimerexpire, pt); 1071 splx(s); 1072 return; 1073 } 1074 splx(s); 1075 pt->pt_overruns++; 1076 } 1077#endif /* !__HAVE_TIMECOUNTER */ 1078} 1079 1080/* BSD routine to get the value of an interval timer. */ 1081/* ARGSUSED */ 1082int 1083sys_getitimer(struct lwp *l, void *v, register_t *retval) 1084{ 1085 struct sys_getitimer_args /* { 1086 syscallarg(int) which; 1087 syscallarg(struct itimerval *) itv; 1088 } */ *uap = v; 1089 struct proc *p = l->l_proc; 1090 struct itimerval aitv; 1091 int error; 1092 1093 error = dogetitimer(p, SCARG(uap, which), &aitv); 1094 if (error) 1095 return error; 1096 return (copyout(&aitv, SCARG(uap, itv), sizeof(struct itimerval))); 1097} 1098 1099int 1100dogetitimer(struct proc *p, int which, struct itimerval *itvp) 1101{ 1102 int s; 1103 1104 if ((u_int)which > ITIMER_PROF) 1105 return (EINVAL); 1106 1107 if ((p->p_timers == NULL) || (p->p_timers->pts_timers[which] == NULL)){ 1108 timerclear(&itvp->it_value); 1109 timerclear(&itvp->it_interval); 1110 } else { 1111 s = splclock(); 1112 timer_gettime(p->p_timers->pts_timers[which], itvp); 1113 splx(s); 1114 } 1115 1116 return 0; 1117} 1118 1119/* BSD routine to set/arm an interval timer. */ 1120/* ARGSUSED */ 1121int 1122sys_setitimer(struct lwp *l, void *v, register_t *retval) 1123{ 1124 struct sys_setitimer_args /* { 1125 syscallarg(int) which; 1126 syscallarg(const struct itimerval *) itv; 1127 syscallarg(struct itimerval *) oitv; 1128 } */ *uap = v; 1129 struct proc *p = l->l_proc; 1130 int which = SCARG(uap, which); 1131 struct sys_getitimer_args getargs; 1132 const struct itimerval *itvp; 1133 struct itimerval aitv; 1134 int error; 1135 1136 if ((u_int)which > ITIMER_PROF) 1137 return (EINVAL); 1138 itvp = SCARG(uap, itv); 1139 if (itvp && 1140 (error = copyin(itvp, &aitv, sizeof(struct itimerval)) != 0)) 1141 return (error); 1142 if (SCARG(uap, oitv) != NULL) { 1143 SCARG(&getargs, which) = which; 1144 SCARG(&getargs, itv) = SCARG(uap, oitv); 1145 if ((error = sys_getitimer(l, &getargs, retval)) != 0) 1146 return (error); 1147 } 1148 if (itvp == 0) 1149 return (0); 1150 1151 return dosetitimer(p, which, &aitv); 1152} 1153 1154int 1155dosetitimer(struct proc *p, int which, struct itimerval *itvp) 1156{ 1157#ifdef __HAVE_TIMECOUNTER 1158 struct timeval now; 1159#endif 1160 struct ptimer *pt; 1161 int s; 1162 1163 if (itimerfix(&itvp->it_value) || itimerfix(&itvp->it_interval)) 1164 return (EINVAL); 1165 1166 /* 1167 * Don't bother allocating data structures if the process just 1168 * wants to clear the timer. 1169 */ 1170 if (!timerisset(&itvp->it_value) && 1171 ((p->p_timers == NULL) ||(p->p_timers->pts_timers[which] == NULL))) 1172 return (0); 1173 1174 if (p->p_timers == NULL) 1175 timers_alloc(p); 1176 if (p->p_timers->pts_timers[which] == NULL) { 1177 pt = pool_get(&ptimer_pool, PR_WAITOK); 1178 pt->pt_ev.sigev_notify = SIGEV_SIGNAL; 1179 pt->pt_ev.sigev_value.sival_int = which; 1180 pt->pt_overruns = 0; 1181 pt->pt_proc = p; 1182 pt->pt_type = which; 1183 pt->pt_entry = which; 1184 switch (which) { 1185 case ITIMER_REAL: 1186 callout_init(&pt->pt_ch); 1187 pt->pt_ev.sigev_signo = SIGALRM; 1188 break; 1189 case ITIMER_VIRTUAL: 1190 pt->pt_active = 0; 1191 pt->pt_ev.sigev_signo = SIGVTALRM; 1192 break; 1193 case ITIMER_PROF: 1194 pt->pt_active = 0; 1195 pt->pt_ev.sigev_signo = SIGPROF; 1196 break; 1197 } 1198 } else 1199 pt = p->p_timers->pts_timers[which]; 1200 1201 pt->pt_time = *itvp; 1202 p->p_timers->pts_timers[which] = pt; 1203 1204 s = splclock(); 1205 if ((which == ITIMER_REAL) && timerisset(&pt->pt_time.it_value)) { 1206 /* Convert to absolute time */ 1207#ifdef __HAVE_TIMECOUNTER 1208 /* XXX need to wrap in splclock for timecounters case? */ 1209 getmicrotime(&now); 1210 timeradd(&pt->pt_time.it_value, &now, &pt->pt_time.it_value); 1211#else /* !__HAVE_TIMECOUNTER */ 1212 timeradd(&pt->pt_time.it_value, &time, &pt->pt_time.it_value); 1213#endif /* !__HAVE_TIMECOUNTER */ 1214 } 1215 timer_settime(pt); 1216 splx(s); 1217 1218 return (0); 1219} 1220 1221/* Utility routines to manage the array of pointers to timers. */ 1222void 1223timers_alloc(struct proc *p) 1224{ 1225 int i; 1226 struct ptimers *pts; 1227 1228 pts = pool_get(&ptimers_pool, PR_WAITOK); 1229 LIST_INIT(&pts->pts_virtual); 1230 LIST_INIT(&pts->pts_prof); 1231 for (i = 0; i < TIMER_MAX; i++) 1232 pts->pts_timers[i] = NULL; 1233 pts->pts_fired = 0; 1234 p->p_timers = pts; 1235} 1236 1237/* 1238 * Clean up the per-process timers. If "which" is set to TIMERS_ALL, 1239 * then clean up all timers and free all the data structures. If 1240 * "which" is set to TIMERS_POSIX, only clean up the timers allocated 1241 * by timer_create(), not the BSD setitimer() timers, and only free the 1242 * structure if none of those remain. 1243 */ 1244void 1245timers_free(struct proc *p, int which) 1246{ 1247 int i, s; 1248 struct ptimers *pts; 1249 struct ptimer *pt, *ptn; 1250 struct timeval tv; 1251 1252 if (p->p_timers) { 1253 pts = p->p_timers; 1254 if (which == TIMERS_ALL) 1255 i = 0; 1256 else { 1257 s = splclock(); 1258 timerclear(&tv); 1259 for (ptn = LIST_FIRST(&p->p_timers->pts_virtual); 1260 ptn && ptn != pts->pts_timers[ITIMER_VIRTUAL]; 1261 ptn = LIST_NEXT(ptn, pt_list)) 1262 timeradd(&tv, &ptn->pt_time.it_value, &tv); 1263 LIST_FIRST(&p->p_timers->pts_virtual) = NULL; 1264 if (ptn) { 1265 timeradd(&tv, &ptn->pt_time.it_value, 1266 &ptn->pt_time.it_value); 1267 LIST_INSERT_HEAD(&p->p_timers->pts_virtual, 1268 ptn, pt_list); 1269 } 1270 1271 timerclear(&tv); 1272 for (ptn = LIST_FIRST(&p->p_timers->pts_prof); 1273 ptn && ptn != pts->pts_timers[ITIMER_PROF]; 1274 ptn = LIST_NEXT(ptn, pt_list)) 1275 timeradd(&tv, &ptn->pt_time.it_value, &tv); 1276 LIST_FIRST(&p->p_timers->pts_prof) = NULL; 1277 if (ptn) { 1278 timeradd(&tv, &ptn->pt_time.it_value, 1279 &ptn->pt_time.it_value); 1280 LIST_INSERT_HEAD(&p->p_timers->pts_prof, ptn, 1281 pt_list); 1282 } 1283 splx(s); 1284 i = 3; 1285 } 1286 for ( ; i < TIMER_MAX; i++) 1287 if ((pt = pts->pts_timers[i]) != NULL) { 1288 if (pt->pt_type == CLOCK_REALTIME) 1289 callout_stop(&pt->pt_ch); 1290 pts->pts_timers[i] = NULL; 1291 pool_put(&ptimer_pool, pt); 1292 } 1293 if ((pts->pts_timers[0] == NULL) && 1294 (pts->pts_timers[1] == NULL) && 1295 (pts->pts_timers[2] == NULL)) { 1296 p->p_timers = NULL; 1297 pool_put(&ptimers_pool, pts); 1298 } 1299 } 1300} 1301 1302/* 1303 * Check that a proposed value to load into the .it_value or 1304 * .it_interval part of an interval timer is acceptable, and 1305 * fix it to have at least minimal value (i.e. if it is less 1306 * than the resolution of the clock, round it up.) 1307 */ 1308int 1309itimerfix(struct timeval *tv) 1310{ 1311 1312 if (tv->tv_sec < 0 || tv->tv_usec < 0 || tv->tv_usec >= 1000000) 1313 return (EINVAL); 1314 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 1315 tv->tv_usec = tick; 1316 return (0); 1317} 1318 1319#ifdef __HAVE_TIMECOUNTER 1320int 1321itimespecfix(struct timespec *ts) 1322{ 1323 1324 if (ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000) 1325 return (EINVAL); 1326 if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000) 1327 ts->tv_nsec = tick * 1000; 1328 return (0); 1329} 1330#endif /* __HAVE_TIMECOUNTER */ 1331 1332/* 1333 * Decrement an interval timer by a specified number 1334 * of microseconds, which must be less than a second, 1335 * i.e. < 1000000. If the timer expires, then reload 1336 * it. In this case, carry over (usec - old value) to 1337 * reduce the value reloaded into the timer so that 1338 * the timer does not drift. This routine assumes 1339 * that it is called in a context where the timers 1340 * on which it is operating cannot change in value. 1341 */ 1342int 1343itimerdecr(struct ptimer *pt, int usec) 1344{ 1345 struct itimerval *itp; 1346 1347 itp = &pt->pt_time; 1348 if (itp->it_value.tv_usec < usec) { 1349 if (itp->it_value.tv_sec == 0) { 1350 /* expired, and already in next interval */ 1351 usec -= itp->it_value.tv_usec; 1352 goto expire; 1353 } 1354 itp->it_value.tv_usec += 1000000; 1355 itp->it_value.tv_sec--; 1356 } 1357 itp->it_value.tv_usec -= usec; 1358 usec = 0; 1359 if (timerisset(&itp->it_value)) 1360 return (1); 1361 /* expired, exactly at end of interval */ 1362expire: 1363 if (timerisset(&itp->it_interval)) { 1364 itp->it_value = itp->it_interval; 1365 itp->it_value.tv_usec -= usec; 1366 if (itp->it_value.tv_usec < 0) { 1367 itp->it_value.tv_usec += 1000000; 1368 itp->it_value.tv_sec--; 1369 } 1370 timer_settime(pt); 1371 } else 1372 itp->it_value.tv_usec = 0; /* sec is already 0 */ 1373 return (0); 1374} 1375 1376void 1377itimerfire(struct ptimer *pt) 1378{ 1379 struct proc *p = pt->pt_proc; 1380 1381 if (pt->pt_ev.sigev_notify == SIGEV_SIGNAL) { 1382 /* 1383 * No RT signal infrastructure exists at this time; 1384 * just post the signal number and throw away the 1385 * value. 1386 */ 1387 if (sigismember(&p->p_sigpend.sp_set, pt->pt_ev.sigev_signo)) 1388 pt->pt_overruns++; 1389 else { 1390 ksiginfo_t ksi; 1391 KSI_INIT(&ksi); 1392 ksi.ksi_signo = pt->pt_ev.sigev_signo; 1393 ksi.ksi_code = SI_TIMER; 1394 ksi.ksi_sigval = pt->pt_ev.sigev_value; 1395 pt->pt_poverruns = pt->pt_overruns; 1396 pt->pt_overruns = 0; 1397 mutex_enter(&proclist_mutex); 1398 kpsignal(p, &ksi, NULL); 1399 mutex_exit(&proclist_mutex); 1400 } 1401 } 1402} 1403 1404/* 1405 * ratecheck(): simple time-based rate-limit checking. see ratecheck(9) 1406 * for usage and rationale. 1407 */ 1408int 1409ratecheck(struct timeval *lasttime, const struct timeval *mininterval) 1410{ 1411 struct timeval tv, delta; 1412 int rv = 0; 1413#ifndef __HAVE_TIMECOUNTER 1414 int s; 1415#endif 1416 1417#ifdef __HAVE_TIMECOUNTER 1418 getmicrouptime(&tv); 1419#else /* !__HAVE_TIMECOUNTER */ 1420 s = splclock(); 1421 tv = mono_time; 1422 splx(s); 1423#endif /* !__HAVE_TIMECOUNTER */ 1424 timersub(&tv, lasttime, &delta); 1425 1426 /* 1427 * check for 0,0 is so that the message will be seen at least once, 1428 * even if interval is huge. 1429 */ 1430 if (timercmp(&delta, mininterval, >=) || 1431 (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { 1432 *lasttime = tv; 1433 rv = 1; 1434 } 1435 1436 return (rv); 1437} 1438 1439/* 1440 * ppsratecheck(): packets (or events) per second limitation. 1441 */ 1442int 1443ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) 1444{ 1445 struct timeval tv, delta; 1446 int rv; 1447#ifndef __HAVE_TIMECOUNTER 1448 int s; 1449#endif 1450 1451#ifdef __HAVE_TIMECOUNTER 1452 getmicrouptime(&tv); 1453#else /* !__HAVE_TIMECOUNTER */ 1454 s = splclock(); 1455 tv = mono_time; 1456 splx(s); 1457#endif /* !__HAVE_TIMECOUNTER */ 1458 timersub(&tv, lasttime, &delta); 1459 1460 /* 1461 * check for 0,0 is so that the message will be seen at least once. 1462 * if more than one second have passed since the last update of 1463 * lasttime, reset the counter. 1464 * 1465 * we do increment *curpps even in *curpps < maxpps case, as some may 1466 * try to use *curpps for stat purposes as well. 1467 */ 1468 if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) || 1469 delta.tv_sec >= 1) { 1470 *lasttime = tv; 1471 *curpps = 0; 1472 } 1473 if (maxpps < 0) 1474 rv = 1; 1475 else if (*curpps < maxpps) 1476 rv = 1; 1477 else 1478 rv = 0; 1479 1480#if 1 /*DIAGNOSTIC?*/ 1481 /* be careful about wrap-around */ 1482 if (*curpps + 1 > *curpps) 1483 *curpps = *curpps + 1; 1484#else 1485 /* 1486 * assume that there's not too many calls to this function. 1487 * not sure if the assumption holds, as it depends on *caller's* 1488 * behavior, not the behavior of this function. 1489 * IMHO it is wrong to make assumption on the caller's behavior, 1490 * so the above #if is #if 1, not #ifdef DIAGNOSTIC. 1491 */ 1492 *curpps = *curpps + 1; 1493#endif 1494 1495 return (rv); 1496} 1497