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