1 /* $OpenBSD: kern_time.c,v 1.65 2008/09/19 23:36:24 djm Exp $ */ 2 /* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)kern_time.c 8.4 (Berkeley) 5/26/95 33 */ 34 35 #include <sys/param.h> 36 #include <sys/resourcevar.h> 37 #include <sys/kernel.h> 38 #include <sys/systm.h> 39 #include <sys/proc.h> 40 #include <sys/vnode.h> 41 #include <sys/signalvar.h> 42 #ifdef __HAVE_TIMECOUNTER 43 #include <sys/timetc.h> 44 #endif 45 46 #include <sys/mount.h> 47 #include <sys/syscallargs.h> 48 49 #include <machine/cpu.h> 50 51 void itimerround(struct timeval *); 52 53 /* 54 * Time of day and interval timer support. 55 * 56 * These routines provide the kernel entry points to get and set 57 * the time-of-day and per-process interval timers. Subroutines 58 * here provide support for adding and subtracting timeval structures 59 * and decrementing interval timers, optionally reloading the interval 60 * timers when they expire. 61 */ 62 63 /* This function is used by clock_settime and settimeofday */ 64 #ifdef __HAVE_TIMECOUNTER 65 int 66 settime(struct timespec *ts) 67 { 68 struct timespec now; 69 70 71 /* 72 * Don't allow the time to be set forward so far it will wrap 73 * and become negative, thus allowing an attacker to bypass 74 * the next check below. The cutoff is 1 year before rollover 75 * occurs, so even if the attacker uses adjtime(2) to move 76 * the time past the cutoff, it will take a very long time 77 * to get to the wrap point. 78 * 79 * XXX: we check against INT_MAX since on 64-bit 80 * platforms, sizeof(int) != sizeof(long) and 81 * time_t is 32 bits even when atv.tv_sec is 64 bits. 82 */ 83 if (ts->tv_sec > INT_MAX - 365*24*60*60) { 84 printf("denied attempt to set clock forward to %ld\n", 85 ts->tv_sec); 86 return (EPERM); 87 } 88 /* 89 * If the system is secure, we do not allow the time to be 90 * set to an earlier value (it may be slowed using adjtime, 91 * but not set back). This feature prevent interlopers from 92 * setting arbitrary time stamps on files. 93 */ 94 nanotime(&now); 95 if (securelevel > 1 && timespeccmp(ts, &now, <)) { 96 printf("denied attempt to set clock back %ld seconds\n", 97 now.tv_sec - ts->tv_sec); 98 return (EPERM); 99 } 100 101 tc_setclock(ts); 102 resettodr(); 103 104 return (0); 105 } 106 #else 107 int 108 settime(struct timespec *ts) 109 { 110 struct timeval delta, tvv, *tv; 111 int s; 112 113 /* XXX - Ugh. */ 114 tv = &tvv; 115 tvv.tv_sec = ts->tv_sec; 116 tvv.tv_usec = ts->tv_nsec / 1000; 117 118 /* 119 * Don't allow the time to be set forward so far it will wrap 120 * and become negative, thus allowing an attacker to bypass 121 * the next check below. The cutoff is 1 year before rollover 122 * occurs, so even if the attacker uses adjtime(2) to move 123 * the time past the cutoff, it will take a very long time 124 * to get to the wrap point. 125 * 126 * XXX: we check against INT_MAX since on 64-bit 127 * platforms, sizeof(int) != sizeof(long) and 128 * time_t is 32 bits even when atv.tv_sec is 64 bits. 129 */ 130 if (tv->tv_sec > INT_MAX - 365*24*60*60) { 131 printf("denied attempt to set clock forward to %ld\n", 132 tv->tv_sec); 133 return (EPERM); 134 } 135 /* 136 * If the system is secure, we do not allow the time to be 137 * set to an earlier value (it may be slowed using adjtime, 138 * but not set back). This feature prevent interlopers from 139 * setting arbitrary time stamps on files. 140 */ 141 if (securelevel > 1 && timercmp(tv, &time, <)) { 142 printf("denied attempt to set clock back %ld seconds\n", 143 time_second - tv->tv_sec); 144 return (EPERM); 145 } 146 147 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 148 s = splclock(); 149 timersub(tv, &time, &delta); 150 time = *tv; 151 timeradd(&boottime, &delta, &boottime); 152 splx(s); 153 resettodr(); 154 155 return (0); 156 } 157 #endif 158 159 /* ARGSUSED */ 160 int 161 sys_clock_gettime(struct proc *p, void *v, register_t *retval) 162 { 163 struct sys_clock_gettime_args /* { 164 syscallarg(clockid_t) clock_id; 165 syscallarg(struct timespec *) tp; 166 } */ *uap = v; 167 clockid_t clock_id; 168 struct timespec ats; 169 170 clock_id = SCARG(uap, clock_id); 171 switch (clock_id) { 172 case CLOCK_REALTIME: 173 nanotime(&ats); 174 break; 175 case CLOCK_MONOTONIC: 176 nanouptime(&ats); 177 break; 178 case CLOCK_PROF: 179 ats.tv_sec = p->p_rtime.tv_sec; 180 ats.tv_nsec = p->p_rtime.tv_usec * 1000; 181 break; 182 default: 183 return (EINVAL); 184 } 185 186 return copyout(&ats, SCARG(uap, tp), sizeof(ats)); 187 } 188 189 /* ARGSUSED */ 190 int 191 sys_clock_settime(struct proc *p, void *v, register_t *retval) 192 { 193 struct sys_clock_settime_args /* { 194 syscallarg(clockid_t) clock_id; 195 syscallarg(const struct timespec *) tp; 196 } */ *uap = v; 197 struct timespec ats; 198 clockid_t clock_id; 199 int error; 200 201 if ((error = suser(p, 0)) != 0) 202 return (error); 203 204 if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0) 205 return (error); 206 207 clock_id = SCARG(uap, clock_id); 208 switch (clock_id) { 209 case CLOCK_REALTIME: 210 if ((error = settime(&ats)) != 0) 211 return (error); 212 break; 213 default: /* Other clocks are read-only */ 214 return (EINVAL); 215 } 216 217 return (0); 218 } 219 220 int 221 sys_clock_getres(struct proc *p, void *v, register_t *retval) 222 { 223 struct sys_clock_getres_args /* { 224 syscallarg(clockid_t) clock_id; 225 syscallarg(struct timespec *) tp; 226 } */ *uap = v; 227 clockid_t clock_id; 228 struct timespec ts; 229 int error = 0; 230 231 clock_id = SCARG(uap, clock_id); 232 switch (clock_id) { 233 case CLOCK_REALTIME: 234 case CLOCK_MONOTONIC: 235 ts.tv_sec = 0; 236 ts.tv_nsec = 1000000000 / hz; 237 break; 238 default: 239 return (EINVAL); 240 } 241 242 if (SCARG(uap, tp)) 243 error = copyout(&ts, SCARG(uap, tp), sizeof (ts)); 244 245 return error; 246 } 247 248 /* ARGSUSED */ 249 int 250 sys_nanosleep(struct proc *p, void *v, register_t *retval) 251 { 252 static int nanowait; 253 struct sys_nanosleep_args/* { 254 syscallarg(const struct timespec *) rqtp; 255 syscallarg(struct timespec *) rmtp; 256 } */ *uap = v; 257 struct timespec rqt, rmt; 258 struct timespec sts, ets; 259 struct timeval tv; 260 int error, error1; 261 262 error = copyin((const void *)SCARG(uap, rqtp), (void *)&rqt, 263 sizeof(struct timespec)); 264 if (error) 265 return (error); 266 267 TIMESPEC_TO_TIMEVAL(&tv, &rqt); 268 if (itimerfix(&tv)) 269 return (EINVAL); 270 271 if (SCARG(uap, rmtp)) 272 getnanouptime(&sts); 273 274 error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", 275 MAX(1, tvtohz(&tv))); 276 if (error == ERESTART) 277 error = EINTR; 278 if (error == EWOULDBLOCK) 279 error = 0; 280 281 if (SCARG(uap, rmtp)) { 282 getnanouptime(&ets); 283 284 timespecsub(&ets, &sts, &sts); 285 timespecsub(&rqt, &sts, &rmt); 286 287 if (rmt.tv_sec < 0) 288 timespecclear(&rmt); 289 290 error1 = copyout((void *)&rmt, (void *)SCARG(uap,rmtp), 291 sizeof(rmt)); 292 if (error1 != 0) 293 error = error1; 294 } 295 296 return error; 297 } 298 299 /* ARGSUSED */ 300 int 301 sys_gettimeofday(struct proc *p, void *v, register_t *retval) 302 { 303 struct sys_gettimeofday_args /* { 304 syscallarg(struct timeval *) tp; 305 syscallarg(struct timezone *) tzp; 306 } */ *uap = v; 307 struct timeval atv; 308 int error = 0; 309 310 if (SCARG(uap, tp)) { 311 microtime(&atv); 312 if ((error = copyout((void *)&atv, (void *)SCARG(uap, tp), 313 sizeof (atv)))) 314 return (error); 315 } 316 if (SCARG(uap, tzp)) 317 error = copyout((void *)&tz, (void *)SCARG(uap, tzp), 318 sizeof (tz)); 319 return (error); 320 } 321 322 /* ARGSUSED */ 323 int 324 sys_settimeofday(struct proc *p, void *v, register_t *retval) 325 { 326 struct sys_settimeofday_args /* { 327 syscallarg(const struct timeval *) tv; 328 syscallarg(const struct timezone *) tzp; 329 } */ *uap = v; 330 struct timezone atz; 331 struct timeval atv; 332 int error; 333 334 if ((error = suser(p, 0))) 335 return (error); 336 /* Verify all parameters before changing time. */ 337 if (SCARG(uap, tv) && (error = copyin((void *)SCARG(uap, tv), 338 (void *)&atv, sizeof(atv)))) 339 return (error); 340 if (SCARG(uap, tzp) && (error = copyin((void *)SCARG(uap, tzp), 341 (void *)&atz, sizeof(atz)))) 342 return (error); 343 if (SCARG(uap, tv)) { 344 struct timespec ts; 345 346 TIMEVAL_TO_TIMESPEC(&atv, &ts); 347 if ((error = settime(&ts)) != 0) 348 return (error); 349 } 350 if (SCARG(uap, tzp)) 351 tz = atz; 352 return (0); 353 } 354 355 #ifdef __HAVE_TIMECOUNTER 356 struct timeval adjtimedelta; /* unapplied time correction */ 357 #else 358 int tickdelta; /* current clock skew, us. per tick */ 359 long timedelta; /* unapplied time correction, us. */ 360 long bigadj = 1000000; /* use 10x skew above bigadj us. */ 361 int64_t ntp_tick_permanent; 362 int64_t ntp_tick_acc; 363 #endif 364 365 /* ARGSUSED */ 366 int 367 sys_adjfreq(struct proc *p, void *v, register_t *retval) 368 { 369 struct sys_adjfreq_args /* { 370 syscallarg(const int64_t *) freq; 371 syscallarg(int64_t *) oldfreq; 372 } */ *uap = v; 373 int error; 374 int64_t f; 375 #ifndef __HAVE_TIMECOUNTER 376 int s; 377 378 if (SCARG(uap, oldfreq)) { 379 f = ntp_tick_permanent * hz; 380 if ((error = copyout((void *)&f, (void *)SCARG(uap, oldfreq), 381 sizeof(int64_t)))) 382 return (error); 383 } 384 if (SCARG(uap, freq)) { 385 if ((error = suser(p, 0))) 386 return (error); 387 if ((error = copyin((void *)SCARG(uap, freq), (void *)&f, 388 sizeof(int64_t)))) 389 return (error); 390 s = splclock(); 391 ntp_tick_permanent = f / hz; 392 splx(s); 393 } 394 #else 395 if (SCARG(uap, oldfreq)) { 396 if ((error = tc_adjfreq(&f, NULL)) != 0) 397 return (error); 398 if ((error = copyout(&f, SCARG(uap, oldfreq), sizeof(f))) != 0) 399 return (error); 400 } 401 if (SCARG(uap, freq)) { 402 if ((error = suser(p, 0))) 403 return (error); 404 if ((error = copyin(SCARG(uap, freq), &f, sizeof(f))) != 0) 405 return (error); 406 if ((error = tc_adjfreq(NULL, &f)) != 0) 407 return (error); 408 } 409 #endif 410 return (0); 411 } 412 413 /* ARGSUSED */ 414 int 415 sys_adjtime(struct proc *p, void *v, register_t *retval) 416 { 417 struct sys_adjtime_args /* { 418 syscallarg(const struct timeval *) delta; 419 syscallarg(struct timeval *) olddelta; 420 } */ *uap = v; 421 #ifdef __HAVE_TIMECOUNTER 422 int error; 423 424 if (SCARG(uap, olddelta)) 425 if ((error = copyout((void *)&adjtimedelta, 426 (void *)SCARG(uap, olddelta), sizeof(struct timeval)))) 427 return (error); 428 429 if (SCARG(uap, delta)) { 430 if ((error = suser(p, 0))) 431 return (error); 432 433 if ((error = copyin((void *)SCARG(uap, delta), 434 (void *)&adjtimedelta, sizeof(struct timeval)))) 435 return (error); 436 } 437 438 /* Normalize the correction. */ 439 while (adjtimedelta.tv_usec >= 1000000) { 440 adjtimedelta.tv_usec -= 1000000; 441 adjtimedelta.tv_sec += 1; 442 } 443 while (adjtimedelta.tv_usec < 0) { 444 adjtimedelta.tv_usec += 1000000; 445 adjtimedelta.tv_sec -= 1; 446 } 447 return (0); 448 #else 449 struct timeval atv; 450 long ndelta, ntickdelta, odelta; 451 int s, error; 452 453 if (!SCARG(uap, delta)) { 454 s = splclock(); 455 odelta = timedelta; 456 splx(s); 457 goto out; 458 } 459 if ((error = suser(p, 0))) 460 return (error); 461 if ((error = copyin((void *)SCARG(uap, delta), (void *)&atv, 462 sizeof(struct timeval)))) 463 return (error); 464 465 /* 466 * Compute the total correction and the rate at which to apply it. 467 * Round the adjustment down to a whole multiple of the per-tick 468 * delta, so that after some number of incremental changes in 469 * hardclock(), tickdelta will become zero, lest the correction 470 * overshoot and start taking us away from the desired final time. 471 */ 472 if (atv.tv_sec > LONG_MAX / 1000000L) 473 ndelta = LONG_MAX; 474 else if (atv.tv_sec < LONG_MIN / 1000000L) 475 ndelta = LONG_MIN; 476 else { 477 ndelta = atv.tv_sec * 1000000L; 478 odelta = ndelta; 479 ndelta += atv.tv_usec; 480 if (atv.tv_usec > 0 && ndelta <= odelta) 481 ndelta = LONG_MAX; 482 else if (atv.tv_usec < 0 && ndelta >= odelta) 483 ndelta = LONG_MIN; 484 } 485 486 if (ndelta > bigadj || ndelta < -bigadj) 487 ntickdelta = 10 * tickadj; 488 else 489 ntickdelta = tickadj; 490 if (ndelta % ntickdelta) 491 ndelta = ndelta / ntickdelta * ntickdelta; 492 493 /* 494 * To make hardclock()'s job easier, make the per-tick delta negative 495 * if we want time to run slower; then hardclock can simply compute 496 * tick + tickdelta, and subtract tickdelta from timedelta. 497 */ 498 if (ndelta < 0) 499 ntickdelta = -ntickdelta; 500 s = splclock(); 501 odelta = timedelta; 502 timedelta = ndelta; 503 tickdelta = ntickdelta; 504 splx(s); 505 506 out: 507 if (SCARG(uap, olddelta)) { 508 atv.tv_sec = odelta / 1000000; 509 atv.tv_usec = odelta % 1000000; 510 if ((error = copyout((void *)&atv, (void *)SCARG(uap, olddelta), 511 sizeof(struct timeval)))) 512 return (error); 513 } 514 return (0); 515 #endif 516 } 517 518 519 /* 520 * Get value of an interval timer. The process virtual and 521 * profiling virtual time timers are kept in the p_stats area, since 522 * they can be swapped out. These are kept internally in the 523 * way they are specified externally: in time until they expire. 524 * 525 * The real time interval timer is kept in the process table slot 526 * for the process, and its value (it_value) is kept as an 527 * absolute time rather than as a delta, so that it is easy to keep 528 * periodic real-time signals from drifting. 529 * 530 * Virtual time timers are processed in the hardclock() routine of 531 * kern_clock.c. The real time timer is processed by a timeout 532 * routine, called from the softclock() routine. Since a callout 533 * may be delayed in real time due to interrupt processing in the system, 534 * it is possible for the real time timeout routine (realitexpire, given below), 535 * to be delayed in real time past when it is supposed to occur. It 536 * does not suffice, therefore, to reload the real timer .it_value from the 537 * real time timers .it_interval. Rather, we compute the next time in 538 * absolute time the timer should go off. 539 */ 540 /* ARGSUSED */ 541 int 542 sys_getitimer(struct proc *p, void *v, register_t *retval) 543 { 544 struct sys_getitimer_args /* { 545 syscallarg(int) which; 546 syscallarg(struct itimerval *) itv; 547 } */ *uap = v; 548 struct itimerval aitv; 549 int s; 550 551 if (SCARG(uap, which) < ITIMER_REAL || SCARG(uap, which) > ITIMER_PROF) 552 return (EINVAL); 553 s = splclock(); 554 if (SCARG(uap, which) == ITIMER_REAL) { 555 struct timeval now; 556 557 getmicrouptime(&now); 558 /* 559 * Convert from absolute to relative time in .it_value 560 * part of real time timer. If time for real time timer 561 * has passed return 0, else return difference between 562 * current time and time for the timer to go off. 563 */ 564 aitv = p->p_realtimer; 565 if (timerisset(&aitv.it_value)) { 566 if (timercmp(&aitv.it_value, &now, <)) 567 timerclear(&aitv.it_value); 568 else 569 timersub(&aitv.it_value, &now, 570 &aitv.it_value); 571 } 572 } else 573 aitv = p->p_stats->p_timer[SCARG(uap, which)]; 574 splx(s); 575 return (copyout((void *)&aitv, (void *)SCARG(uap, itv), 576 sizeof (struct itimerval))); 577 } 578 579 /* ARGSUSED */ 580 int 581 sys_setitimer(struct proc *p, void *v, register_t *retval) 582 { 583 struct sys_setitimer_args /* { 584 syscallarg(int) which; 585 syscallarg(const struct itimerval *) itv; 586 syscallarg(struct itimerval *) oitv; 587 } */ *uap = v; 588 struct sys_getitimer_args getargs; 589 struct itimerval aitv; 590 const struct itimerval *itvp; 591 int error; 592 int timo; 593 594 if (SCARG(uap, which) < ITIMER_REAL || SCARG(uap, which) > ITIMER_PROF) 595 return (EINVAL); 596 itvp = SCARG(uap, itv); 597 if (itvp && (error = copyin((void *)itvp, (void *)&aitv, 598 sizeof(struct itimerval)))) 599 return (error); 600 if (SCARG(uap, oitv) != NULL) { 601 SCARG(&getargs, which) = SCARG(uap, which); 602 SCARG(&getargs, itv) = SCARG(uap, oitv); 603 if ((error = sys_getitimer(p, &getargs, retval))) 604 return (error); 605 } 606 if (itvp == 0) 607 return (0); 608 if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) 609 return (EINVAL); 610 if (SCARG(uap, which) == ITIMER_REAL) { 611 struct timeval ctv; 612 613 timeout_del(&p->p_realit_to); 614 getmicrouptime(&ctv); 615 if (timerisset(&aitv.it_value)) { 616 timo = tvtohz(&aitv.it_value); 617 timeout_add(&p->p_realit_to, timo); 618 timeradd(&aitv.it_value, &ctv, &aitv.it_value); 619 } 620 p->p_realtimer = aitv; 621 } else { 622 int s; 623 624 itimerround(&aitv.it_interval); 625 s = splclock(); 626 p->p_stats->p_timer[SCARG(uap, which)] = aitv; 627 splx(s); 628 } 629 630 return (0); 631 } 632 633 /* 634 * Real interval timer expired: 635 * send process whose timer expired an alarm signal. 636 * If time is not set up to reload, then just return. 637 * Else compute next time timer should go off which is > current time. 638 * This is where delay in processing this timeout causes multiple 639 * SIGALRM calls to be compressed into one. 640 */ 641 void 642 realitexpire(void *arg) 643 { 644 struct proc *p; 645 646 p = (struct proc *)arg; 647 psignal(p, SIGALRM); 648 if (!timerisset(&p->p_realtimer.it_interval)) { 649 timerclear(&p->p_realtimer.it_value); 650 return; 651 } 652 for (;;) { 653 struct timeval ctv, ntv; 654 int timo; 655 656 timeradd(&p->p_realtimer.it_value, 657 &p->p_realtimer.it_interval, &p->p_realtimer.it_value); 658 getmicrouptime(&ctv); 659 if (timercmp(&p->p_realtimer.it_value, &ctv, >)) { 660 ntv = p->p_realtimer.it_value; 661 timersub(&ntv, &ctv, &ntv); 662 timo = tvtohz(&ntv) - 1; 663 if (timo <= 0) 664 timo = 1; 665 if ((p->p_flag & P_WEXIT) == 0) 666 timeout_add(&p->p_realit_to, timo); 667 return; 668 } 669 } 670 } 671 672 /* 673 * Check that a proposed value to load into the .it_value or 674 * .it_interval part of an interval timer is acceptable. 675 */ 676 int 677 itimerfix(struct timeval *tv) 678 { 679 680 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 681 tv->tv_usec < 0 || tv->tv_usec >= 1000000) 682 return (EINVAL); 683 684 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 685 tv->tv_usec = tick; 686 687 return (0); 688 } 689 690 /* 691 * Nonzero timer interval smaller than the resolution of the 692 * system clock are rounded up. 693 */ 694 void 695 itimerround(struct timeval *tv) 696 { 697 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 698 tv->tv_usec = tick; 699 } 700 701 /* 702 * Decrement an interval timer by a specified number 703 * of microseconds, which must be less than a second, 704 * i.e. < 1000000. If the timer expires, then reload 705 * it. In this case, carry over (usec - old value) to 706 * reduce the value reloaded into the timer so that 707 * the timer does not drift. This routine assumes 708 * that it is called in a context where the timers 709 * on which it is operating cannot change in value. 710 */ 711 int 712 itimerdecr(struct itimerval *itp, int usec) 713 { 714 715 if (itp->it_value.tv_usec < usec) { 716 if (itp->it_value.tv_sec == 0) { 717 /* expired, and already in next interval */ 718 usec -= itp->it_value.tv_usec; 719 goto expire; 720 } 721 itp->it_value.tv_usec += 1000000; 722 itp->it_value.tv_sec--; 723 } 724 itp->it_value.tv_usec -= usec; 725 usec = 0; 726 if (timerisset(&itp->it_value)) 727 return (1); 728 /* expired, exactly at end of interval */ 729 expire: 730 if (timerisset(&itp->it_interval)) { 731 itp->it_value = itp->it_interval; 732 itp->it_value.tv_usec -= usec; 733 if (itp->it_value.tv_usec < 0) { 734 itp->it_value.tv_usec += 1000000; 735 itp->it_value.tv_sec--; 736 } 737 } else 738 itp->it_value.tv_usec = 0; /* sec is already 0 */ 739 return (0); 740 } 741 742 /* 743 * ratecheck(): simple time-based rate-limit checking. see ratecheck(9) 744 * for usage and rationale. 745 */ 746 int 747 ratecheck(struct timeval *lasttime, const struct timeval *mininterval) 748 { 749 struct timeval tv, delta; 750 int rv = 0; 751 752 getmicrouptime(&tv); 753 754 timersub(&tv, lasttime, &delta); 755 756 /* 757 * check for 0,0 is so that the message will be seen at least once, 758 * even if interval is huge. 759 */ 760 if (timercmp(&delta, mininterval, >=) || 761 (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { 762 *lasttime = tv; 763 rv = 1; 764 } 765 766 return (rv); 767 } 768 769 /* 770 * ppsratecheck(): packets (or events) per second limitation. 771 */ 772 int 773 ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) 774 { 775 struct timeval tv, delta; 776 int rv; 777 778 microuptime(&tv); 779 780 timersub(&tv, lasttime, &delta); 781 782 /* 783 * check for 0,0 is so that the message will be seen at least once. 784 * if more than one second have passed since the last update of 785 * lasttime, reset the counter. 786 * 787 * we do increment *curpps even in *curpps < maxpps case, as some may 788 * try to use *curpps for stat purposes as well. 789 */ 790 if (maxpps == 0) 791 rv = 0; 792 else if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) || 793 delta.tv_sec >= 1) { 794 *lasttime = tv; 795 *curpps = 0; 796 rv = 1; 797 } else if (maxpps < 0) 798 rv = 1; 799 else if (*curpps < maxpps) 800 rv = 1; 801 else 802 rv = 0; 803 804 #if 1 /*DIAGNOSTIC?*/ 805 /* be careful about wrap-around */ 806 if (*curpps + 1 > *curpps) 807 *curpps = *curpps + 1; 808 #else 809 /* 810 * assume that there's not too many calls to this function. 811 * not sure if the assumption holds, as it depends on *caller's* 812 * behavior, not the behavior of this function. 813 * IMHO it is wrong to make assumption on the caller's behavior, 814 * so the above #if is #if 1, not #ifdef DIAGNOSTIC. 815 */ 816 *curpps = *curpps + 1; 817 #endif 818 819 return (rv); 820 } 821