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