kern_time.c revision 108142
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * Redistribution and use in source and binary forms, with or without 61541Srgrimes * modification, are permitted provided that the following conditions 71541Srgrimes * are met: 81541Srgrimes * 1. Redistributions of source code must retain the above copyright 91541Srgrimes * notice, this list of conditions and the following disclaimer. 101541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111541Srgrimes * notice, this list of conditions and the following disclaimer in the 121541Srgrimes * documentation and/or other materials provided with the distribution. 131541Srgrimes * 3. All advertising materials mentioning features or use of this software 141541Srgrimes * must display the following acknowledgement: 151541Srgrimes * This product includes software developed by the University of 161541Srgrimes * California, Berkeley and its contributors. 171541Srgrimes * 4. Neither the name of the University nor the names of its contributors 181541Srgrimes * may be used to endorse or promote products derived from this software 191541Srgrimes * without specific prior written permission. 201541Srgrimes * 211541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311541Srgrimes * SUCH DAMAGE. 321541Srgrimes * 331541Srgrimes * @(#)kern_time.c 8.1 (Berkeley) 6/10/93 3450477Speter * $FreeBSD: head/sys/kern/kern_time.c 108142 2002-12-20 23:54:47Z sam $ 351541Srgrimes */ 361541Srgrimes 37106369Srwatson#include "opt_mac.h" 38106369Srwatson 391541Srgrimes#include <sys/param.h> 4048274Speter#include <sys/systm.h> 4176166Smarkm#include <sys/lock.h> 4276166Smarkm#include <sys/mutex.h> 4312221Sbde#include <sys/sysproto.h> 441541Srgrimes#include <sys/resourcevar.h> 453308Sphk#include <sys/signalvar.h> 461541Srgrimes#include <sys/kernel.h> 47106369Srwatson#include <sys/mac.h> 481541Srgrimes#include <sys/systm.h> 4925583Speter#include <sys/sysent.h> 501541Srgrimes#include <sys/proc.h> 5125656Speter#include <sys/time.h> 5258377Sphk#include <sys/timetc.h> 531541Srgrimes#include <sys/vnode.h> 5476166Smarkm 5526335Speter#include <vm/vm.h> 5626335Speter#include <vm/vm_extern.h> 571541Srgrimes 589369Sdgstruct timezone tz; 599369Sdg 608876Srgrimes/* 611541Srgrimes * Time of day and interval timer support. 621541Srgrimes * 631541Srgrimes * These routines provide the kernel entry points to get and set 641541Srgrimes * the time-of-day and per-process interval timers. Subroutines 651541Srgrimes * here provide support for adding and subtracting timeval structures 661541Srgrimes * and decrementing interval timers, optionally reloading the interval 671541Srgrimes * timers when they expire. 681541Srgrimes */ 691541Srgrimes 7092723Salfredstatic int nanosleep1(struct thread *td, struct timespec *rqt, 7192723Salfred struct timespec *rmt); 7294343Sjhbstatic int settime(struct thread *, struct timeval *); 7392723Salfredstatic void timevalfix(struct timeval *); 7492723Salfredstatic void no_lease_updatetime(int); 7513016Sbde 7630739Sphkstatic void 7730739Sphkno_lease_updatetime(deltat) 7830739Sphk int deltat; 7930739Sphk{ 8030739Sphk} 8130739Sphk 8292723Salfredvoid (*lease_updatetime)(int) = no_lease_updatetime; 8330739Sphk 8425583Speterstatic int 85102074Sphksettime(struct thread *td, struct timeval *tv) 8625583Speter{ 8745433Snsayer struct timeval delta, tv1, tv2; 8845438Snsayer static struct timeval maxtime, laststep; 8933690Sphk struct timespec ts; 9025583Speter int s; 9125583Speter 9225656Speter s = splclock(); 9333818Sbde microtime(&tv1); 9435029Sphk delta = *tv; 9535029Sphk timevalsub(&delta, &tv1); 9625583Speter 9725583Speter /* 9833818Sbde * If the system is secure, we do not allow the time to be 9945433Snsayer * set to a value earlier than 1 second less than the highest 10045433Snsayer * time we have yet seen. The worst a miscreant can do in 10145433Snsayer * this circumstance is "freeze" time. He couldn't go 10245433Snsayer * back to the past. 10345438Snsayer * 10445438Snsayer * We similarly do not allow the clock to be stepped more 10545438Snsayer * than one second, nor more than once per second. This allows 10645438Snsayer * a miscreant to make the clock march double-time, but no worse. 10725583Speter */ 10894343Sjhb if (securelevel_gt(td->td_ucred, 1) != 0) { 10945433Snsayer if (delta.tv_sec < 0 || delta.tv_usec < 0) { 11045437Smjacob /* 11145438Snsayer * Update maxtime to latest time we've seen. 11245437Smjacob */ 11345437Smjacob if (tv1.tv_sec > maxtime.tv_sec) 11445437Smjacob maxtime = tv1; 11545437Smjacob tv2 = *tv; 11645437Smjacob timevalsub(&tv2, &maxtime); 11745437Smjacob if (tv2.tv_sec < -1) { 11845437Smjacob tv->tv_sec = maxtime.tv_sec - 1; 11945433Snsayer printf("Time adjustment clamped to -1 second\n"); 12045433Snsayer } 12145437Smjacob } else { 12245438Snsayer if (tv1.tv_sec == laststep.tv_sec) { 12345438Snsayer splx(s); 12445438Snsayer return (EPERM); 12545438Snsayer } 12645438Snsayer if (delta.tv_sec > 1) { 12745438Snsayer tv->tv_sec = tv1.tv_sec + 1; 12845438Snsayer printf("Time adjustment clamped to +1 second\n"); 12945438Snsayer } 13045438Snsayer laststep = *tv; 13145433Snsayer } 13233818Sbde } 13333818Sbde 13433690Sphk ts.tv_sec = tv->tv_sec; 13533690Sphk ts.tv_nsec = tv->tv_usec * 1000; 13694343Sjhb mtx_lock(&Giant); 13758377Sphk tc_setclock(&ts); 13825583Speter (void) splsoftclock(); 13925583Speter lease_updatetime(delta.tv_sec); 14025583Speter splx(s); 14125583Speter resettodr(); 14294343Sjhb mtx_unlock(&Giant); 14325583Speter return (0); 14425583Speter} 14525583Speter 14612221Sbde#ifndef _SYS_SYSPROTO_H_ 14725583Speterstruct clock_gettime_args { 14825583Speter clockid_t clock_id; 14925583Speter struct timespec *tp; 15025583Speter}; 15125583Speter#endif 15225656Speter 15382746Sdillon/* 15482746Sdillon * MPSAFE 15582746Sdillon */ 15625583Speter/* ARGSUSED */ 15725583Speterint 158102074Sphkclock_gettime(struct thread *td, struct clock_gettime_args *uap) 15925583Speter{ 16025583Speter struct timespec ats; 16125583Speter 162107849Salfred if (uap->clock_id != CLOCK_REALTIME) 16325583Speter return (EINVAL); 16482746Sdillon mtx_lock(&Giant); 16533690Sphk nanotime(&ats); 16682746Sdillon mtx_unlock(&Giant); 167107849Salfred return (copyout(&ats, uap->tp, sizeof(ats))); 16825583Speter} 16925583Speter 17025583Speter#ifndef _SYS_SYSPROTO_H_ 17125583Speterstruct clock_settime_args { 17225583Speter clockid_t clock_id; 17325583Speter const struct timespec *tp; 17425583Speter}; 17525583Speter#endif 17625656Speter 17782746Sdillon/* 17882746Sdillon * MPSAFE 17982746Sdillon */ 18025583Speter/* ARGSUSED */ 18125583Speterint 182102074Sphkclock_settime(struct thread *td, struct clock_settime_args *uap) 18325583Speter{ 18425583Speter struct timeval atv; 18525583Speter struct timespec ats; 18625583Speter int error; 18725583Speter 188106369Srwatson#ifdef MAC 189106369Srwatson error = mac_check_system_settime(td->td_ucred); 190106369Srwatson if (error) 191106369Srwatson return (error); 192106369Srwatson#endif 19393593Sjhb if ((error = suser(td)) != 0) 19494343Sjhb return (error); 195107849Salfred if (uap->clock_id != CLOCK_REALTIME) 19694343Sjhb return (EINVAL); 197107849Salfred if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0) 19894343Sjhb return (error); 19994343Sjhb if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000) 20094343Sjhb return (EINVAL); 20134901Sphk /* XXX Don't convert nsec->usec and back */ 20225583Speter TIMESPEC_TO_TIMEVAL(&atv, &ats); 20394343Sjhb error = settime(td, &atv); 20482746Sdillon return (error); 20525583Speter} 20625583Speter 20725583Speter#ifndef _SYS_SYSPROTO_H_ 20825583Speterstruct clock_getres_args { 20925583Speter clockid_t clock_id; 21025583Speter struct timespec *tp; 21125583Speter}; 21225583Speter#endif 21325656Speter 21425583Speterint 215102074Sphkclock_getres(struct thread *td, struct clock_getres_args *uap) 21625583Speter{ 21725583Speter struct timespec ts; 21825656Speter int error; 21925583Speter 220107849Salfred if (uap->clock_id != CLOCK_REALTIME) 22125583Speter return (EINVAL); 22225656Speter error = 0; 223107849Salfred if (uap->tp) { 22425583Speter ts.tv_sec = 0; 225103964Sbde /* 226103964Sbde * Round up the result of the division cheaply by adding 1. 227103964Sbde * Rounding up is especially important if rounding down 228103964Sbde * would give 0. Perfect rounding is unimportant. 229103964Sbde */ 230103964Sbde ts.tv_nsec = 1000000000 / tc_getfrequency() + 1; 231107849Salfred error = copyout(&ts, uap->tp, sizeof(ts)); 23225583Speter } 23325656Speter return (error); 23425583Speter} 23525583Speter 23626335Speterstatic int nanowait; 23725656Speter 23826335Speterstatic int 239102074Sphknanosleep1(struct thread *td, struct timespec *rqt, struct timespec *rmt) 24025583Speter{ 24135045Sphk struct timespec ts, ts2, ts3; 24235042Sphk struct timeval tv; 24335042Sphk int error; 24425583Speter 24528773Sbde if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000) 24625656Speter return (EINVAL); 24743301Sdillon if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0)) 24828773Sbde return (0); 24936119Sphk getnanouptime(&ts); 25035029Sphk timespecadd(&ts, rqt); 25135042Sphk TIMESPEC_TO_TIMEVAL(&tv, rqt); 25235042Sphk for (;;) { 25335042Sphk error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", 25435042Sphk tvtohz(&tv)); 25536119Sphk getnanouptime(&ts2); 25635042Sphk if (error != EWOULDBLOCK) { 25735042Sphk if (error == ERESTART) 25835042Sphk error = EINTR; 25935042Sphk if (rmt != NULL) { 26035042Sphk timespecsub(&ts, &ts2); 26135042Sphk if (ts.tv_sec < 0) 26235042Sphk timespecclear(&ts); 26335042Sphk *rmt = ts; 26435042Sphk } 26535042Sphk return (error); 26635042Sphk } 26735029Sphk if (timespeccmp(&ts2, &ts, >=)) 26835042Sphk return (0); 26935045Sphk ts3 = ts; 27035045Sphk timespecsub(&ts3, &ts2); 27135045Sphk TIMESPEC_TO_TIMEVAL(&tv, &ts3); 27226335Speter } 27326335Speter} 27425583Speter 27526335Speter#ifndef _SYS_SYSPROTO_H_ 27626335Speterstruct nanosleep_args { 27726335Speter struct timespec *rqtp; 27826335Speter struct timespec *rmtp; 27926335Speter}; 28026335Speter#endif 28126335Speter 28282746Sdillon/* 28382746Sdillon * MPSAFE 28482746Sdillon */ 28526335Speter/* ARGSUSED */ 28626335Speterint 287102074Sphknanosleep(struct thread *td, struct nanosleep_args *uap) 28826335Speter{ 28926335Speter struct timespec rmt, rqt; 29082746Sdillon int error; 29126335Speter 292107849Salfred error = copyin(uap->rqtp, &rqt, sizeof(rqt)); 29326335Speter if (error) 29426335Speter return (error); 29582746Sdillon 29682746Sdillon mtx_lock(&Giant); 297107849Salfred if (uap->rmtp) { 298107849Salfred if (!useracc((caddr_t)uap->rmtp, sizeof(rmt), 29982746Sdillon VM_PROT_WRITE)) { 30082746Sdillon error = EFAULT; 30182746Sdillon goto done2; 30282746Sdillon } 30382746Sdillon } 30483366Sjulian error = nanosleep1(td, &rqt, &rmt); 305107849Salfred if (error && uap->rmtp) { 30682746Sdillon int error2; 30782746Sdillon 308107849Salfred error2 = copyout(&rmt, uap->rmtp, sizeof(rmt)); 30926335Speter if (error2) /* XXX shouldn't happen, did useracc() above */ 31082746Sdillon error = error2; 31125583Speter } 31282746Sdillondone2: 31382746Sdillon mtx_unlock(&Giant); 31425656Speter return (error); 31525583Speter} 31625583Speter 31726335Speter#ifndef _SYS_SYSPROTO_H_ 3181541Srgrimesstruct gettimeofday_args { 3191541Srgrimes struct timeval *tp; 3201541Srgrimes struct timezone *tzp; 3211541Srgrimes}; 32212221Sbde#endif 32382746Sdillon/* 32482746Sdillon * MPSAFE 32582746Sdillon */ 3261541Srgrimes/* ARGSUSED */ 3271549Srgrimesint 328102074Sphkgettimeofday(struct thread *td, struct gettimeofday_args *uap) 3291541Srgrimes{ 3301541Srgrimes struct timeval atv; 3311541Srgrimes int error = 0; 3321541Srgrimes 3331541Srgrimes if (uap->tp) { 3341541Srgrimes microtime(&atv); 33599012Salfred error = copyout(&atv, uap->tp, sizeof (atv)); 3361541Srgrimes } 33790836Sphk if (error == 0 && uap->tzp != NULL) { 33890836Sphk mtx_lock(&Giant); 33999012Salfred error = copyout(&tz, uap->tzp, sizeof (tz)); 34090836Sphk mtx_unlock(&Giant); 34182746Sdillon } 3421541Srgrimes return (error); 3431541Srgrimes} 3441541Srgrimes 34512221Sbde#ifndef _SYS_SYSPROTO_H_ 3461541Srgrimesstruct settimeofday_args { 3471541Srgrimes struct timeval *tv; 3481541Srgrimes struct timezone *tzp; 3491541Srgrimes}; 35012221Sbde#endif 35182746Sdillon/* 35282746Sdillon * MPSAFE 35382746Sdillon */ 3541541Srgrimes/* ARGSUSED */ 3551549Srgrimesint 356102074Sphksettimeofday(struct thread *td, struct settimeofday_args *uap) 3571541Srgrimes{ 35825656Speter struct timeval atv; 3591541Srgrimes struct timezone atz; 36082746Sdillon int error = 0; 3611541Srgrimes 362106369Srwatson#ifdef MAC 363106369Srwatson error = mac_check_system_settime(td->td_ucred); 364106369Srwatson if (error) 365106369Srwatson return (error); 366106369Srwatson#endif 36793593Sjhb if ((error = suser(td))) 36894343Sjhb return (error); 3691541Srgrimes /* Verify all parameters before changing time. */ 37025656Speter if (uap->tv) { 37199012Salfred if ((error = copyin(uap->tv, &atv, sizeof(atv)))) 37294343Sjhb return (error); 37394343Sjhb if (atv.tv_usec < 0 || atv.tv_usec >= 1000000) 37494343Sjhb return (EINVAL); 37525656Speter } 3761541Srgrimes if (uap->tzp && 37799012Salfred (error = copyin(uap->tzp, &atz, sizeof(atz)))) 37894343Sjhb return (error); 37994343Sjhb 38094343Sjhb if (uap->tv && (error = settime(td, &atv))) 38194343Sjhb return (error); 38294343Sjhb if (uap->tzp) { 38394343Sjhb mtx_lock(&Giant); 38494343Sjhb tz = atz; 38594343Sjhb mtx_unlock(&Giant); 38682746Sdillon } 38782746Sdillon return (error); 3881541Srgrimes} 38982746Sdillon/* 3901541Srgrimes * Get value of an interval timer. The process virtual and 3911541Srgrimes * profiling virtual time timers are kept in the p_stats area, since 3921541Srgrimes * they can be swapped out. These are kept internally in the 3931541Srgrimes * way they are specified externally: in time until they expire. 3941541Srgrimes * 3951541Srgrimes * The real time interval timer is kept in the process table slot 3961541Srgrimes * for the process, and its value (it_value) is kept as an 3971541Srgrimes * absolute time rather than as a delta, so that it is easy to keep 3981541Srgrimes * periodic real-time signals from drifting. 3991541Srgrimes * 4001541Srgrimes * Virtual time timers are processed in the hardclock() routine of 4011541Srgrimes * kern_clock.c. The real time timer is processed by a timeout 4021541Srgrimes * routine, called from the softclock() routine. Since a callout 4031541Srgrimes * may be delayed in real time due to interrupt processing in the system, 4041541Srgrimes * it is possible for the real time timeout routine (realitexpire, given below), 4051541Srgrimes * to be delayed in real time past when it is supposed to occur. It 4061541Srgrimes * does not suffice, therefore, to reload the real timer .it_value from the 4071541Srgrimes * real time timers .it_interval. Rather, we compute the next time in 4081541Srgrimes * absolute time the timer should go off. 4091541Srgrimes */ 41012221Sbde#ifndef _SYS_SYSPROTO_H_ 4111541Srgrimesstruct getitimer_args { 4121541Srgrimes u_int which; 4131541Srgrimes struct itimerval *itv; 4141541Srgrimes}; 41512221Sbde#endif 41682746Sdillon/* 41782746Sdillon * MPSAFE 41882746Sdillon */ 4191541Srgrimes/* ARGSUSED */ 4201549Srgrimesint 421102074Sphkgetitimer(struct thread *td, struct getitimer_args *uap) 4221541Srgrimes{ 42383366Sjulian struct proc *p = td->td_proc; 42434961Sphk struct timeval ctv; 4251541Srgrimes struct itimerval aitv; 4261541Srgrimes int s; 42782746Sdillon int error; 4281541Srgrimes 4291541Srgrimes if (uap->which > ITIMER_PROF) 4301541Srgrimes return (EINVAL); 43182746Sdillon 43282746Sdillon mtx_lock(&Giant); 43382746Sdillon 43434961Sphk s = splclock(); /* XXX still needed ? */ 4351541Srgrimes if (uap->which == ITIMER_REAL) { 4361541Srgrimes /* 43736128Sbde * Convert from absolute to relative time in .it_value 4381541Srgrimes * part of real time timer. If time for real time timer 4391541Srgrimes * has passed return 0, else return difference between 4401541Srgrimes * current time and time for the timer to go off. 4411541Srgrimes */ 4421541Srgrimes aitv = p->p_realtimer; 44335058Sphk if (timevalisset(&aitv.it_value)) { 44436119Sphk getmicrouptime(&ctv); 44535058Sphk if (timevalcmp(&aitv.it_value, &ctv, <)) 44635058Sphk timevalclear(&aitv.it_value); 4471541Srgrimes else 44834961Sphk timevalsub(&aitv.it_value, &ctv); 44934961Sphk } 45082746Sdillon } else { 4511541Srgrimes aitv = p->p_stats->p_timer[uap->which]; 45282746Sdillon } 4531541Srgrimes splx(s); 45499012Salfred error = copyout(&aitv, uap->itv, sizeof (struct itimerval)); 45582746Sdillon mtx_unlock(&Giant); 45682746Sdillon return(error); 4571541Srgrimes} 4581541Srgrimes 45912221Sbde#ifndef _SYS_SYSPROTO_H_ 4601541Srgrimesstruct setitimer_args { 4611541Srgrimes u_int which; 4621541Srgrimes struct itimerval *itv, *oitv; 4631541Srgrimes}; 46412221Sbde#endif 46582746Sdillon/* 46682746Sdillon * MPSAFE 46782746Sdillon */ 4681541Srgrimes/* ARGSUSED */ 4691549Srgrimesint 470102074Sphksetitimer(struct thread *td, struct setitimer_args *uap) 4711541Srgrimes{ 47283366Sjulian struct proc *p = td->td_proc; 4731541Srgrimes struct itimerval aitv; 47434961Sphk struct timeval ctv; 475102074Sphk struct itimerval *itvp; 47682746Sdillon int s, error = 0; 4771541Srgrimes 4781541Srgrimes if (uap->which > ITIMER_PROF) 4791541Srgrimes return (EINVAL); 4801541Srgrimes itvp = uap->itv; 48199012Salfred if (itvp && (error = copyin(itvp, &aitv, sizeof(struct itimerval)))) 4821541Srgrimes return (error); 48382746Sdillon 48482746Sdillon mtx_lock(&Giant); 48582746Sdillon 48612381Sbde if ((uap->itv = uap->oitv) && 48783366Sjulian (error = getitimer(td, (struct getitimer_args *)uap))) { 48882746Sdillon goto done2; 48982746Sdillon } 49082746Sdillon if (itvp == 0) { 49182746Sdillon error = 0; 49282746Sdillon goto done2; 49382746Sdillon } 49482746Sdillon if (itimerfix(&aitv.it_value)) { 49582746Sdillon error = EINVAL; 49682746Sdillon goto done2; 49782746Sdillon } 49882746Sdillon if (!timevalisset(&aitv.it_value)) { 49935058Sphk timevalclear(&aitv.it_interval); 50082746Sdillon } else if (itimerfix(&aitv.it_interval)) { 50182746Sdillon error = EINVAL; 50282746Sdillon goto done2; 50382746Sdillon } 50434961Sphk s = splclock(); /* XXX: still needed ? */ 5051541Srgrimes if (uap->which == ITIMER_REAL) { 50635058Sphk if (timevalisset(&p->p_realtimer.it_value)) 50769286Sjake callout_stop(&p->p_itcallout); 50835058Sphk if (timevalisset(&aitv.it_value)) 50969286Sjake callout_reset(&p->p_itcallout, tvtohz(&aitv.it_value), 51069286Sjake realitexpire, p); 51136119Sphk getmicrouptime(&ctv); 51235044Sphk timevaladd(&aitv.it_value, &ctv); 5131541Srgrimes p->p_realtimer = aitv; 51482746Sdillon } else { 5151541Srgrimes p->p_stats->p_timer[uap->which] = aitv; 51682746Sdillon } 5171541Srgrimes splx(s); 51882746Sdillondone2: 51982746Sdillon mtx_unlock(&Giant); 52082746Sdillon return (error); 5211541Srgrimes} 5221541Srgrimes 5231541Srgrimes/* 5241541Srgrimes * Real interval timer expired: 5251541Srgrimes * send process whose timer expired an alarm signal. 5261541Srgrimes * If time is not set up to reload, then just return. 5271541Srgrimes * Else compute next time timer should go off which is > current time. 5281541Srgrimes * This is where delay in processing this timeout causes multiple 5291541Srgrimes * SIGALRM calls to be compressed into one. 53036127Sbde * tvtohz() always adds 1 to allow for the time until the next clock 5319327Sbde * interrupt being strictly less than 1 clock tick, but we don't want 5329327Sbde * that here since we want to appear to be in sync with the clock 5339327Sbde * interrupt even when we're delayed. 5341541Srgrimes */ 5351541Srgrimesvoid 536102074Sphkrealitexpire(void *arg) 5371541Srgrimes{ 538102074Sphk struct proc *p; 53935044Sphk struct timeval ctv, ntv; 5401541Srgrimes int s; 5411541Srgrimes 5421541Srgrimes p = (struct proc *)arg; 54373916Sjhb PROC_LOCK(p); 5441541Srgrimes psignal(p, SIGALRM); 54535058Sphk if (!timevalisset(&p->p_realtimer.it_interval)) { 54635058Sphk timevalclear(&p->p_realtimer.it_value); 54773916Sjhb PROC_UNLOCK(p); 5481541Srgrimes return; 5491541Srgrimes } 5501541Srgrimes for (;;) { 55134961Sphk s = splclock(); /* XXX: still neeeded ? */ 5521541Srgrimes timevaladd(&p->p_realtimer.it_value, 5531541Srgrimes &p->p_realtimer.it_interval); 55436119Sphk getmicrouptime(&ctv); 55535058Sphk if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) { 55635044Sphk ntv = p->p_realtimer.it_value; 55735044Sphk timevalsub(&ntv, &ctv); 55869286Sjake callout_reset(&p->p_itcallout, tvtohz(&ntv) - 1, 55969286Sjake realitexpire, p); 5601541Srgrimes splx(s); 56173916Sjhb PROC_UNLOCK(p); 5621541Srgrimes return; 5631541Srgrimes } 5641541Srgrimes splx(s); 5651541Srgrimes } 56673916Sjhb /*NOTREACHED*/ 5671541Srgrimes} 5681541Srgrimes 5691541Srgrimes/* 5701541Srgrimes * Check that a proposed value to load into the .it_value or 5711541Srgrimes * .it_interval part of an interval timer is acceptable, and 5721541Srgrimes * fix it to have at least minimal value (i.e. if it is less 5731541Srgrimes * than the resolution of the clock, round it up.) 5741541Srgrimes */ 5751549Srgrimesint 576102074Sphkitimerfix(struct timeval *tv) 5771541Srgrimes{ 5781541Srgrimes 5791541Srgrimes if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 5801541Srgrimes tv->tv_usec < 0 || tv->tv_usec >= 1000000) 5811541Srgrimes return (EINVAL); 5821541Srgrimes if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 5831541Srgrimes tv->tv_usec = tick; 5841541Srgrimes return (0); 5851541Srgrimes} 5861541Srgrimes 5871541Srgrimes/* 5881541Srgrimes * Decrement an interval timer by a specified number 5891541Srgrimes * of microseconds, which must be less than a second, 5901541Srgrimes * i.e. < 1000000. If the timer expires, then reload 5911541Srgrimes * it. In this case, carry over (usec - old value) to 5921541Srgrimes * reduce the value reloaded into the timer so that 5931541Srgrimes * the timer does not drift. This routine assumes 5941541Srgrimes * that it is called in a context where the timers 5951541Srgrimes * on which it is operating cannot change in value. 5961541Srgrimes */ 5971549Srgrimesint 598102074Sphkitimerdecr(struct itimerval *itp, int usec) 5991541Srgrimes{ 6001541Srgrimes 6011541Srgrimes if (itp->it_value.tv_usec < usec) { 6021541Srgrimes if (itp->it_value.tv_sec == 0) { 6031541Srgrimes /* expired, and already in next interval */ 6041541Srgrimes usec -= itp->it_value.tv_usec; 6051541Srgrimes goto expire; 6061541Srgrimes } 6071541Srgrimes itp->it_value.tv_usec += 1000000; 6081541Srgrimes itp->it_value.tv_sec--; 6091541Srgrimes } 6101541Srgrimes itp->it_value.tv_usec -= usec; 6111541Srgrimes usec = 0; 61235058Sphk if (timevalisset(&itp->it_value)) 6131541Srgrimes return (1); 6141541Srgrimes /* expired, exactly at end of interval */ 6151541Srgrimesexpire: 61635058Sphk if (timevalisset(&itp->it_interval)) { 6171541Srgrimes itp->it_value = itp->it_interval; 6181541Srgrimes itp->it_value.tv_usec -= usec; 6191541Srgrimes if (itp->it_value.tv_usec < 0) { 6201541Srgrimes itp->it_value.tv_usec += 1000000; 6211541Srgrimes itp->it_value.tv_sec--; 6221541Srgrimes } 6231541Srgrimes } else 6241541Srgrimes itp->it_value.tv_usec = 0; /* sec is already 0 */ 6251541Srgrimes return (0); 6261541Srgrimes} 6271541Srgrimes 6281541Srgrimes/* 6291541Srgrimes * Add and subtract routines for timevals. 6301541Srgrimes * N.B.: subtract routine doesn't deal with 6311541Srgrimes * results which are before the beginning, 6321541Srgrimes * it just gets very confused in this case. 6331541Srgrimes * Caveat emptor. 6341541Srgrimes */ 6351549Srgrimesvoid 636102074Sphktimevaladd(struct timeval *t1, struct timeval *t2) 6371541Srgrimes{ 6381541Srgrimes 6391541Srgrimes t1->tv_sec += t2->tv_sec; 6401541Srgrimes t1->tv_usec += t2->tv_usec; 6411541Srgrimes timevalfix(t1); 6421541Srgrimes} 6431541Srgrimes 6441549Srgrimesvoid 645102074Sphktimevalsub(struct timeval *t1, struct timeval *t2) 6461541Srgrimes{ 6471541Srgrimes 6481541Srgrimes t1->tv_sec -= t2->tv_sec; 6491541Srgrimes t1->tv_usec -= t2->tv_usec; 6501541Srgrimes timevalfix(t1); 6511541Srgrimes} 6521541Srgrimes 65312819Sphkstatic void 654102074Sphktimevalfix(struct timeval *t1) 6551541Srgrimes{ 6561541Srgrimes 6571541Srgrimes if (t1->tv_usec < 0) { 6581541Srgrimes t1->tv_sec--; 6591541Srgrimes t1->tv_usec += 1000000; 6601541Srgrimes } 6611541Srgrimes if (t1->tv_usec >= 1000000) { 6621541Srgrimes t1->tv_sec++; 6631541Srgrimes t1->tv_usec -= 1000000; 6641541Srgrimes } 6651541Srgrimes} 666108142Ssam 667108142Ssam#ifndef timersub 668108142Ssam#define timersub(tvp, uvp, vvp) \ 669108142Ssam do { \ 670108142Ssam (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \ 671108142Ssam (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \ 672108142Ssam if ((vvp)->tv_usec < 0) { \ 673108142Ssam (vvp)->tv_sec--; \ 674108142Ssam (vvp)->tv_usec += 1000000; \ 675108142Ssam } \ 676108142Ssam } while (0) 677108142Ssam#endif 678108142Ssam 679108142Ssam/* 680108142Ssam * ratecheck(): simple time-based rate-limit checking. see ratecheck(9) 681108142Ssam * for usage and rationale. 682108142Ssam */ 683108142Ssamint 684108142Ssamratecheck(struct timeval *lasttime, const struct timeval *mininterval) 685108142Ssam{ 686108142Ssam struct timeval tv, delta; 687108142Ssam int rv = 0; 688108142Ssam 689108142Ssam getmicrouptime(&tv); 690108142Ssam timersub(&tv, lasttime, &delta); 691108142Ssam 692108142Ssam /* 693108142Ssam * check for 0,0 is so that the message will be seen at least once, 694108142Ssam * even if interval is huge. 695108142Ssam */ 696108142Ssam if (timevalcmp(&delta, mininterval, >=) || 697108142Ssam (lasttime->tv_sec == 0 && lasttime->tv_usec == 0)) { 698108142Ssam *lasttime = tv; 699108142Ssam rv = 1; 700108142Ssam } 701108142Ssam 702108142Ssam return (rv); 703108142Ssam} 704108142Ssam 705108142Ssam/* 706108142Ssam * ppsratecheck(): packets (or events) per second limitation. 707108142Ssam */ 708108142Ssamint 709108142Ssamppsratecheck(struct timeval *lasttime, int *curpps, int maxpps) 710108142Ssam{ 711108142Ssam struct timeval tv, delta; 712108142Ssam int rv; 713108142Ssam 714108142Ssam getmicrouptime(&tv); 715108142Ssam timersub(&tv, lasttime, &delta); 716108142Ssam 717108142Ssam /* 718108142Ssam * check for 0,0 is so that the message will be seen at least once. 719108142Ssam * if more than one second have passed since the last update of 720108142Ssam * lasttime, reset the counter. 721108142Ssam * 722108142Ssam * we do increment *curpps even in *curpps < maxpps case, as some may 723108142Ssam * try to use *curpps for stat purposes as well. 724108142Ssam */ 725108142Ssam if ((lasttime->tv_sec == 0 && lasttime->tv_usec == 0) || 726108142Ssam delta.tv_sec >= 1) { 727108142Ssam *lasttime = tv; 728108142Ssam *curpps = 0; 729108142Ssam rv = 1; 730108142Ssam } else if (maxpps < 0) 731108142Ssam rv = 1; 732108142Ssam else if (*curpps < maxpps) 733108142Ssam rv = 1; 734108142Ssam else 735108142Ssam rv = 0; 736108142Ssam 737108142Ssam#if 1 /*DIAGNOSTIC?*/ 738108142Ssam /* be careful about wrap-around */ 739108142Ssam if (*curpps + 1 > *curpps) 740108142Ssam *curpps = *curpps + 1; 741108142Ssam#else 742108142Ssam /* 743108142Ssam * assume that there's not too many calls to this function. 744108142Ssam * not sure if the assumption holds, as it depends on *caller's* 745108142Ssam * behavior, not the behavior of this function. 746108142Ssam * IMHO it is wrong to make assumption on the caller's behavior, 747108142Ssam * so the above #if is #if 1, not #ifdef DIAGNOSTIC. 748108142Ssam */ 749108142Ssam *curpps = *curpps + 1; 750108142Ssam#endif 751108142Ssam 752108142Ssam return (rv); 753108142Ssam} 754