1 /* $OpenBSD: kern_time.c,v 1.97 2016/04/28 20:11:20 tedu 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/ktrace.h> 41 #include <sys/vnode.h> 42 #include <sys/signalvar.h> 43 #include <sys/pledge.h> 44 #include <sys/timetc.h> 45 46 #include <sys/mount.h> 47 #include <sys/syscallargs.h> 48 49 50 int64_t adjtimedelta; /* unapplied time correction (microseconds) */ 51 52 /* 53 * Time of day and interval timer support. 54 * 55 * These routines provide the kernel entry points to get and set 56 * the time-of-day and per-process interval timers. Subroutines 57 * here provide support for adding and subtracting timeval structures 58 * and decrementing interval timers, optionally reloading the interval 59 * timers when they expire. 60 */ 61 62 /* This function is used by clock_settime and settimeofday */ 63 int 64 settime(struct timespec *ts) 65 { 66 struct timespec now; 67 68 /* 69 * Adjtime in progress is meaningless or harmful after 70 * setting the clock. Cancel adjtime and then set new time. 71 */ 72 adjtimedelta = 0; 73 74 /* 75 * Don't allow the time to be set forward so far it will wrap 76 * and become negative, thus allowing an attacker to bypass 77 * the next check below. The cutoff is 1 year before rollover 78 * occurs, so even if the attacker uses adjtime(2) to move 79 * the time past the cutoff, it will take a very long time 80 * to get to the wrap point. 81 * 82 * XXX: we check against UINT_MAX until we can figure out 83 * how to deal with the hardware RTCs. 84 */ 85 if (ts->tv_sec > UINT_MAX - 365*24*60*60) { 86 printf("denied attempt to set clock forward to %lld\n", 87 (long long)ts->tv_sec); 88 return (EPERM); 89 } 90 /* 91 * If the system is secure, we do not allow the time to be 92 * set to an earlier value (it may be slowed using adjtime, 93 * but not set back). This feature prevent interlopers from 94 * setting arbitrary time stamps on files. 95 */ 96 nanotime(&now); 97 if (securelevel > 1 && timespeccmp(ts, &now, <)) { 98 printf("denied attempt to set clock back %lld seconds\n", 99 (long long)now.tv_sec - ts->tv_sec); 100 return (EPERM); 101 } 102 103 tc_setrealtimeclock(ts); 104 resettodr(); 105 106 return (0); 107 } 108 109 int 110 clock_gettime(struct proc *p, clockid_t clock_id, struct timespec *tp) 111 { 112 struct bintime bt; 113 struct proc *q; 114 115 switch (clock_id) { 116 case CLOCK_REALTIME: 117 nanotime(tp); 118 break; 119 case CLOCK_UPTIME: 120 binuptime(&bt); 121 bintime_sub(&bt, &naptime); 122 bintime2timespec(&bt, tp); 123 break; 124 case CLOCK_MONOTONIC: 125 nanouptime(tp); 126 break; 127 case CLOCK_PROCESS_CPUTIME_ID: 128 nanouptime(tp); 129 timespecsub(tp, &curcpu()->ci_schedstate.spc_runtime, tp); 130 timespecadd(tp, &p->p_p->ps_tu.tu_runtime, tp); 131 timespecadd(tp, &p->p_rtime, tp); 132 break; 133 case CLOCK_THREAD_CPUTIME_ID: 134 nanouptime(tp); 135 timespecsub(tp, &curcpu()->ci_schedstate.spc_runtime, tp); 136 timespecadd(tp, &p->p_tu.tu_runtime, tp); 137 timespecadd(tp, &p->p_rtime, tp); 138 break; 139 default: 140 /* check for clock from pthread_getcpuclockid() */ 141 if (__CLOCK_TYPE(clock_id) == CLOCK_THREAD_CPUTIME_ID) { 142 q = pfind(__CLOCK_PTID(clock_id) - THREAD_PID_OFFSET); 143 if (q == NULL || q->p_p != p->p_p) 144 return (ESRCH); 145 *tp = q->p_tu.tu_runtime; 146 } else 147 return (EINVAL); 148 } 149 return (0); 150 } 151 152 int 153 sys_clock_gettime(struct proc *p, void *v, register_t *retval) 154 { 155 struct sys_clock_gettime_args /* { 156 syscallarg(clockid_t) clock_id; 157 syscallarg(struct timespec *) tp; 158 } */ *uap = v; 159 struct timespec ats; 160 int error; 161 162 memset(&ats, 0, sizeof(ats)); 163 if ((error = clock_gettime(p, SCARG(uap, clock_id), &ats)) != 0) 164 return (error); 165 166 error = copyout(&ats, SCARG(uap, tp), sizeof(ats)); 167 #ifdef KTRACE 168 if (error == 0 && KTRPOINT(p, KTR_STRUCT)) { 169 KERNEL_LOCK(); 170 ktrabstimespec(p, &ats); 171 KERNEL_UNLOCK(); 172 } 173 #endif 174 return (error); 175 } 176 177 int 178 sys_clock_settime(struct proc *p, void *v, register_t *retval) 179 { 180 struct sys_clock_settime_args /* { 181 syscallarg(clockid_t) clock_id; 182 syscallarg(const struct timespec *) tp; 183 } */ *uap = v; 184 struct timespec ats; 185 clockid_t clock_id; 186 int error; 187 188 if ((error = suser(p, 0)) != 0) 189 return (error); 190 191 if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0) 192 return (error); 193 194 clock_id = SCARG(uap, clock_id); 195 switch (clock_id) { 196 case CLOCK_REALTIME: 197 if ((error = settime(&ats)) != 0) 198 return (error); 199 break; 200 default: /* Other clocks are read-only */ 201 return (EINVAL); 202 } 203 204 return (0); 205 } 206 207 int 208 sys_clock_getres(struct proc *p, void *v, register_t *retval) 209 { 210 struct sys_clock_getres_args /* { 211 syscallarg(clockid_t) clock_id; 212 syscallarg(struct timespec *) tp; 213 } */ *uap = v; 214 clockid_t clock_id; 215 struct timespec ts; 216 struct proc *q; 217 int error = 0; 218 219 memset(&ts, 0, sizeof(ts)); 220 clock_id = SCARG(uap, clock_id); 221 switch (clock_id) { 222 case CLOCK_REALTIME: 223 case CLOCK_MONOTONIC: 224 case CLOCK_UPTIME: 225 case CLOCK_PROCESS_CPUTIME_ID: 226 case CLOCK_THREAD_CPUTIME_ID: 227 ts.tv_sec = 0; 228 ts.tv_nsec = 1000000000 / hz; 229 break; 230 default: 231 /* check for clock from pthread_getcpuclockid() */ 232 if (__CLOCK_TYPE(clock_id) == CLOCK_THREAD_CPUTIME_ID) { 233 q = pfind(__CLOCK_PTID(clock_id) - THREAD_PID_OFFSET); 234 if (q == NULL || q->p_p != p->p_p) 235 return (ESRCH); 236 ts.tv_sec = 0; 237 ts.tv_nsec = 1000000000 / hz; 238 } else 239 return (EINVAL); 240 } 241 242 if (SCARG(uap, tp)) { 243 error = copyout(&ts, SCARG(uap, tp), sizeof (ts)); 244 #ifdef KTRACE 245 if (error == 0 && KTRPOINT(p, KTR_STRUCT)) { 246 KERNEL_LOCK(); 247 ktrreltimespec(p, &ts); 248 KERNEL_UNLOCK(); 249 } 250 #endif 251 } 252 253 return error; 254 } 255 256 int 257 sys_nanosleep(struct proc *p, void *v, register_t *retval) 258 { 259 static int nanowait; 260 struct sys_nanosleep_args/* { 261 syscallarg(const struct timespec *) rqtp; 262 syscallarg(struct timespec *) rmtp; 263 } */ *uap = v; 264 struct timespec rqt, rmt; 265 struct timespec sts, ets; 266 struct timespec *rmtp; 267 struct timeval tv; 268 int error, error1; 269 270 rmtp = SCARG(uap, rmtp); 271 error = copyin(SCARG(uap, rqtp), &rqt, sizeof(struct timespec)); 272 if (error) 273 return (error); 274 #ifdef KTRACE 275 if (KTRPOINT(p, KTR_STRUCT)) { 276 KERNEL_LOCK(); 277 ktrreltimespec(p, &rqt); 278 KERNEL_UNLOCK(); 279 } 280 #endif 281 282 TIMESPEC_TO_TIMEVAL(&tv, &rqt); 283 if (itimerfix(&tv)) 284 return (EINVAL); 285 286 if (rmtp) 287 getnanouptime(&sts); 288 289 error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", 290 MAX(1, tvtohz(&tv))); 291 if (error == ERESTART) 292 error = EINTR; 293 if (error == EWOULDBLOCK) 294 error = 0; 295 296 if (rmtp) { 297 getnanouptime(&ets); 298 299 memset(&rmt, 0, sizeof(rmt)); 300 timespecsub(&ets, &sts, &sts); 301 timespecsub(&rqt, &sts, &rmt); 302 303 if (rmt.tv_sec < 0) 304 timespecclear(&rmt); 305 306 error1 = copyout(&rmt, rmtp, sizeof(rmt)); 307 if (error1 != 0) 308 error = error1; 309 #ifdef KTRACE 310 if (error1 == 0 && KTRPOINT(p, KTR_STRUCT)) { 311 KERNEL_LOCK(); 312 ktrreltimespec(p, &rmt); 313 KERNEL_UNLOCK(); 314 } 315 #endif 316 } 317 318 return error; 319 } 320 321 int 322 sys_gettimeofday(struct proc *p, void *v, register_t *retval) 323 { 324 struct sys_gettimeofday_args /* { 325 syscallarg(struct timeval *) tp; 326 syscallarg(struct timezone *) tzp; 327 } */ *uap = v; 328 struct timeval atv; 329 struct timeval *tp; 330 struct timezone *tzp; 331 int error = 0; 332 333 tp = SCARG(uap, tp); 334 tzp = SCARG(uap, tzp); 335 336 if (tp) { 337 memset(&atv, 0, sizeof(atv)); 338 microtime(&atv); 339 if ((error = copyout(&atv, tp, sizeof (atv)))) 340 return (error); 341 #ifdef KTRACE 342 if (KTRPOINT(p, KTR_STRUCT)) { 343 KERNEL_LOCK(); 344 ktrabstimeval(p, &atv); 345 KERNEL_UNLOCK(); 346 } 347 #endif 348 } 349 if (tzp) 350 error = copyout(&tz, tzp, sizeof (tz)); 351 return (error); 352 } 353 354 int 355 sys_settimeofday(struct proc *p, void *v, register_t *retval) 356 { 357 struct sys_settimeofday_args /* { 358 syscallarg(const struct timeval *) tv; 359 syscallarg(const struct timezone *) tzp; 360 } */ *uap = v; 361 struct timezone atz; 362 struct timeval atv; 363 const struct timeval *tv; 364 const struct timezone *tzp; 365 int error; 366 367 tv = SCARG(uap, tv); 368 tzp = SCARG(uap, tzp); 369 370 if ((error = suser(p, 0))) 371 return (error); 372 /* Verify all parameters before changing time. */ 373 if (tv && (error = copyin(tv, &atv, sizeof(atv)))) 374 return (error); 375 if (tzp && (error = copyin(tzp, &atz, sizeof(atz)))) 376 return (error); 377 if (tv) { 378 struct timespec ts; 379 380 TIMEVAL_TO_TIMESPEC(&atv, &ts); 381 if ((error = settime(&ts)) != 0) 382 return (error); 383 } 384 if (tzp) 385 tz = atz; 386 return (0); 387 } 388 389 int 390 sys_adjfreq(struct proc *p, void *v, register_t *retval) 391 { 392 struct sys_adjfreq_args /* { 393 syscallarg(const int64_t *) freq; 394 syscallarg(int64_t *) oldfreq; 395 } */ *uap = v; 396 int error; 397 int64_t f; 398 const int64_t *freq = SCARG(uap, freq); 399 int64_t *oldfreq = SCARG(uap, oldfreq); 400 if (oldfreq) { 401 if ((error = tc_adjfreq(&f, NULL))) 402 return (error); 403 if ((error = copyout(&f, oldfreq, sizeof(f)))) 404 return (error); 405 } 406 if (freq) { 407 if ((error = suser(p, 0))) 408 return (error); 409 if ((error = copyin(freq, &f, sizeof(f)))) 410 return (error); 411 if ((error = tc_adjfreq(NULL, &f))) 412 return (error); 413 } 414 return (0); 415 } 416 417 int 418 sys_adjtime(struct proc *p, void *v, register_t *retval) 419 { 420 struct sys_adjtime_args /* { 421 syscallarg(const struct timeval *) delta; 422 syscallarg(struct timeval *) olddelta; 423 } */ *uap = v; 424 const struct timeval *delta = SCARG(uap, delta); 425 struct timeval *olddelta = SCARG(uap, olddelta); 426 struct timeval atv; 427 int error; 428 429 error = pledge_adjtime(p, delta); 430 if (error) 431 return error; 432 433 if (olddelta) { 434 memset(&atv, 0, sizeof(atv)); 435 atv.tv_sec = adjtimedelta / 1000000; 436 atv.tv_usec = adjtimedelta % 1000000; 437 if (atv.tv_usec < 0) { 438 atv.tv_usec += 1000000; 439 atv.tv_sec--; 440 } 441 442 if ((error = copyout(&atv, olddelta, sizeof(struct timeval)))) 443 return (error); 444 } 445 446 if (delta) { 447 if ((error = suser(p, 0))) 448 return (error); 449 450 if ((error = copyin(delta, &atv, sizeof(struct timeval)))) 451 return (error); 452 453 /* XXX Check for overflow? */ 454 adjtimedelta = (int64_t)atv.tv_sec * 1000000 + atv.tv_usec; 455 } 456 457 return (0); 458 } 459 460 461 struct mutex itimer_mtx = MUTEX_INITIALIZER(IPL_CLOCK); 462 463 /* 464 * Get value of an interval timer. The process virtual and 465 * profiling virtual time timers are kept internally in the 466 * way they are specified externally: in time until they expire. 467 * 468 * The real time interval timer's it_value, in contrast, is kept as an 469 * absolute time rather than as a delta, so that it is easy to keep 470 * periodic real-time signals from drifting. 471 * 472 * Virtual time timers are processed in the hardclock() routine of 473 * kern_clock.c. The real time timer is processed by a timeout 474 * routine, called from the softclock() routine. Since a callout 475 * may be delayed in real time due to interrupt processing in the system, 476 * it is possible for the real time timeout routine (realitexpire, given below), 477 * to be delayed in real time past when it is supposed to occur. It 478 * does not suffice, therefore, to reload the real timer .it_value from the 479 * real time timers .it_interval. Rather, we compute the next time in 480 * absolute time the timer should go off. 481 */ 482 int 483 sys_getitimer(struct proc *p, void *v, register_t *retval) 484 { 485 struct sys_getitimer_args /* { 486 syscallarg(int) which; 487 syscallarg(struct itimerval *) itv; 488 } */ *uap = v; 489 struct itimerval aitv; 490 int which; 491 492 which = SCARG(uap, which); 493 494 if (which < ITIMER_REAL || which > ITIMER_PROF) 495 return (EINVAL); 496 memset(&aitv, 0, sizeof(aitv)); 497 mtx_enter(&itimer_mtx); 498 aitv.it_interval.tv_sec = p->p_p->ps_timer[which].it_interval.tv_sec; 499 aitv.it_interval.tv_usec = p->p_p->ps_timer[which].it_interval.tv_usec; 500 aitv.it_value.tv_sec = p->p_p->ps_timer[which].it_value.tv_sec; 501 aitv.it_value.tv_usec = p->p_p->ps_timer[which].it_value.tv_usec; 502 mtx_leave(&itimer_mtx); 503 504 if (which == ITIMER_REAL) { 505 struct timeval now; 506 507 getmicrouptime(&now); 508 /* 509 * Convert from absolute to relative time in .it_value 510 * part of real time timer. If time for real time timer 511 * has passed return 0, else return difference between 512 * current time and time for the timer to go off. 513 */ 514 if (timerisset(&aitv.it_value)) { 515 if (timercmp(&aitv.it_value, &now, <)) 516 timerclear(&aitv.it_value); 517 else 518 timersub(&aitv.it_value, &now, 519 &aitv.it_value); 520 } 521 } 522 523 return (copyout(&aitv, SCARG(uap, itv), sizeof (struct itimerval))); 524 } 525 526 int 527 sys_setitimer(struct proc *p, void *v, register_t *retval) 528 { 529 struct sys_setitimer_args /* { 530 syscallarg(int) which; 531 syscallarg(const struct itimerval *) itv; 532 syscallarg(struct itimerval *) oitv; 533 } */ *uap = v; 534 struct sys_getitimer_args getargs; 535 struct itimerval aitv; 536 const struct itimerval *itvp; 537 struct itimerval *oitv; 538 struct process *pr = p->p_p; 539 int error; 540 int timo; 541 int which; 542 543 which = SCARG(uap, which); 544 oitv = SCARG(uap, oitv); 545 546 if (which < ITIMER_REAL || which > ITIMER_PROF) 547 return (EINVAL); 548 itvp = SCARG(uap, itv); 549 if (itvp && (error = copyin((void *)itvp, (void *)&aitv, 550 sizeof(struct itimerval)))) 551 return (error); 552 if (oitv != NULL) { 553 SCARG(&getargs, which) = which; 554 SCARG(&getargs, itv) = oitv; 555 if ((error = sys_getitimer(p, &getargs, retval))) 556 return (error); 557 } 558 if (itvp == 0) 559 return (0); 560 if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) 561 return (EINVAL); 562 if (which == ITIMER_REAL) { 563 struct timeval ctv; 564 565 timeout_del(&pr->ps_realit_to); 566 getmicrouptime(&ctv); 567 if (timerisset(&aitv.it_value)) { 568 timo = tvtohz(&aitv.it_value); 569 timeout_add(&pr->ps_realit_to, timo); 570 timeradd(&aitv.it_value, &ctv, &aitv.it_value); 571 } 572 pr->ps_timer[ITIMER_REAL] = aitv; 573 } else { 574 itimerround(&aitv.it_interval); 575 mtx_enter(&itimer_mtx); 576 pr->ps_timer[which] = aitv; 577 mtx_leave(&itimer_mtx); 578 } 579 580 return (0); 581 } 582 583 /* 584 * Real interval timer expired: 585 * send process whose timer expired an alarm signal. 586 * If time is not set up to reload, then just return. 587 * Else compute next time timer should go off which is > current time. 588 * This is where delay in processing this timeout causes multiple 589 * SIGALRM calls to be compressed into one. 590 */ 591 void 592 realitexpire(void *arg) 593 { 594 struct process *pr = arg; 595 struct itimerval *tp = &pr->ps_timer[ITIMER_REAL]; 596 597 prsignal(pr, SIGALRM); 598 if (!timerisset(&tp->it_interval)) { 599 timerclear(&tp->it_value); 600 return; 601 } 602 for (;;) { 603 struct timeval ctv, ntv; 604 int timo; 605 606 timeradd(&tp->it_value, &tp->it_interval, &tp->it_value); 607 getmicrouptime(&ctv); 608 if (timercmp(&tp->it_value, &ctv, >)) { 609 ntv = tp->it_value; 610 timersub(&ntv, &ctv, &ntv); 611 timo = tvtohz(&ntv) - 1; 612 if (timo <= 0) 613 timo = 1; 614 if ((pr->ps_flags & PS_EXITING) == 0) 615 timeout_add(&pr->ps_realit_to, timo); 616 return; 617 } 618 } 619 } 620 621 /* 622 * Check that a timespec value is legit 623 */ 624 int 625 timespecfix(struct timespec *ts) 626 { 627 if (ts->tv_sec < 0 || 628 ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000) 629 return (EINVAL); 630 if (ts->tv_sec > 100000000) 631 ts->tv_sec = 100000000; 632 return (0); 633 } 634 635 /* 636 * Check that a proposed value to load into the .it_value or 637 * .it_interval part of an interval timer is acceptable. 638 */ 639 int 640 itimerfix(struct timeval *tv) 641 { 642 643 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 644 tv->tv_usec < 0 || tv->tv_usec >= 1000000) 645 return (EINVAL); 646 647 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 648 tv->tv_usec = tick; 649 650 return (0); 651 } 652 653 /* 654 * Nonzero timer interval smaller than the resolution of the 655 * system clock are rounded up. 656 */ 657 void 658 itimerround(struct timeval *tv) 659 { 660 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 661 tv->tv_usec = tick; 662 } 663 664 /* 665 * Decrement an interval timer by a specified number 666 * of microseconds, which must be less than a second, 667 * i.e. < 1000000. If the timer expires, then reload 668 * it. In this case, carry over (usec - old value) to 669 * reduce the value reloaded into the timer so that 670 * the timer does not drift. This routine assumes 671 * that it is called in a context where the timers 672 * on which it is operating cannot change in value. 673 */ 674 int 675 itimerdecr(struct itimerval *itp, int usec) 676 { 677 mtx_enter(&itimer_mtx); 678 if (itp->it_value.tv_usec < usec) { 679 if (itp->it_value.tv_sec == 0) { 680 /* expired, and already in next interval */ 681 usec -= itp->it_value.tv_usec; 682 goto expire; 683 } 684 itp->it_value.tv_usec += 1000000; 685 itp->it_value.tv_sec--; 686 } 687 itp->it_value.tv_usec -= usec; 688 usec = 0; 689 if (timerisset(&itp->it_value)) { 690 mtx_leave(&itimer_mtx); 691 return (1); 692 } 693 /* expired, exactly at end of interval */ 694 expire: 695 if (timerisset(&itp->it_interval)) { 696 itp->it_value = itp->it_interval; 697 itp->it_value.tv_usec -= usec; 698 if (itp->it_value.tv_usec < 0) { 699 itp->it_value.tv_usec += 1000000; 700 itp->it_value.tv_sec--; 701 } 702 } else 703 itp->it_value.tv_usec = 0; /* sec is already 0 */ 704 mtx_leave(&itimer_mtx); 705 return (0); 706 } 707 708 /* 709 * ratecheck(): simple time-based rate-limit checking. see ratecheck(9) 710 * for usage and rationale. 711 */ 712 int 713 ratecheck(struct timeval *lasttime, const struct timeval *mininterval) 714 { 715 struct timeval tv, delta; 716 int rv = 0; 717 718 getmicrouptime(&tv); 719 720 timersub(&tv, lasttime, &delta); 721 722 /* 723 * check for 0,0 is so that the message will be seen at least once, 724 * even if interval is huge. 725 */ 726 if (timercmp(&delta, mininterval, >=) || 727 (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { 728 *lasttime = tv; 729 rv = 1; 730 } 731 732 return (rv); 733 } 734 735 /* 736 * ppsratecheck(): packets (or events) per second limitation. 737 */ 738 int 739 ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) 740 { 741 struct timeval tv, delta; 742 int rv; 743 744 microuptime(&tv); 745 746 timersub(&tv, lasttime, &delta); 747 748 /* 749 * check for 0,0 is so that the message will be seen at least once. 750 * if more than one second have passed since the last update of 751 * lasttime, reset the counter. 752 * 753 * we do increment *curpps even in *curpps < maxpps case, as some may 754 * try to use *curpps for stat purposes as well. 755 */ 756 if (maxpps == 0) 757 rv = 0; 758 else if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) || 759 delta.tv_sec >= 1) { 760 *lasttime = tv; 761 *curpps = 0; 762 rv = 1; 763 } else if (maxpps < 0) 764 rv = 1; 765 else if (*curpps < maxpps) 766 rv = 1; 767 else 768 rv = 0; 769 770 #if 1 /*DIAGNOSTIC?*/ 771 /* be careful about wrap-around */ 772 if (*curpps + 1 > *curpps) 773 *curpps = *curpps + 1; 774 #else 775 /* 776 * assume that there's not too many calls to this function. 777 * not sure if the assumption holds, as it depends on *caller's* 778 * behavior, not the behavior of this function. 779 * IMHO it is wrong to make assumption on the caller's behavior, 780 * so the above #if is #if 1, not #ifdef DIAGNOSTIC. 781 */ 782 *curpps = *curpps + 1; 783 #endif 784 785 return (rv); 786 } 787 788