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