kern_time.c revision 34961
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 3434961Sphk * $Id: kern_time.c,v 1.43 1998/03/26 20:51:41 phk Exp $ 351541Srgrimes */ 361541Srgrimes 371541Srgrimes#include <sys/param.h> 3812221Sbde#include <sys/sysproto.h> 391541Srgrimes#include <sys/resourcevar.h> 403308Sphk#include <sys/signalvar.h> 411541Srgrimes#include <sys/kernel.h> 421541Srgrimes#include <sys/systm.h> 4325583Speter#include <sys/sysent.h> 441541Srgrimes#include <sys/proc.h> 4525656Speter#include <sys/time.h> 461541Srgrimes#include <sys/vnode.h> 4726335Speter#include <vm/vm.h> 4826335Speter#include <vm/vm_extern.h> 491541Srgrimes 509369Sdgstruct timezone tz; 519369Sdg 528876Srgrimes/* 531541Srgrimes * Time of day and interval timer support. 541541Srgrimes * 551541Srgrimes * These routines provide the kernel entry points to get and set 561541Srgrimes * the time-of-day and per-process interval timers. Subroutines 571541Srgrimes * here provide support for adding and subtracting timeval structures 581541Srgrimes * and decrementing interval timers, optionally reloading the interval 591541Srgrimes * timers when they expire. 601541Srgrimes */ 611541Srgrimes 6228773Sbdestatic int nanosleep1 __P((struct proc *p, struct timespec *rqt, 6328773Sbde struct timespec *rmt)); 6425656Speterstatic int settime __P((struct timeval *)); 6513016Sbdestatic void timevalfix __P((struct timeval *)); 6630994Sphkstatic void no_lease_updatetime __P((int)); 6713016Sbde 6830739Sphkstatic void 6930739Sphkno_lease_updatetime(deltat) 7030739Sphk int deltat; 7130739Sphk{ 7230739Sphk} 7330739Sphk 7430739Sphkvoid (*lease_updatetime) __P((int)) = no_lease_updatetime; 7530739Sphk 7625583Speterstatic int 7725583Spetersettime(tv) 7825583Speter struct timeval *tv; 7925583Speter{ 8033818Sbde struct timeval delta, tv1; 8133690Sphk struct timespec ts; 8225583Speter struct proc *p; 8325583Speter int s; 8425583Speter 8525656Speter s = splclock(); 8633818Sbde microtime(&tv1); 8733818Sbde delta.tv_sec = tv->tv_sec - tv1.tv_sec; 8833818Sbde delta.tv_usec = tv->tv_usec - tv1.tv_usec; 8925583Speter timevalfix(&delta); 9025583Speter 9125583Speter /* 9233818Sbde * If the system is secure, we do not allow the time to be 9333818Sbde * set to an earlier value (it may be slowed using adjtime, 9433818Sbde * but not set back). This feature prevent interlopers from 9533818Sbde * setting arbitrary time stamps on files. 9625583Speter */ 9733818Sbde if (delta.tv_sec < 0 && securelevel > 1) { 9833818Sbde splx(s); 9933818Sbde return (EPERM); 10033818Sbde } 10133818Sbde 10233690Sphk ts.tv_sec = tv->tv_sec; 10333690Sphk ts.tv_nsec = tv->tv_usec * 1000; 10433690Sphk set_timecounter(&ts); 10525583Speter (void) splsoftclock(); 10625583Speter timevaladd(&boottime, &delta); 10725583Speter timevaladd(&runtime, &delta); 10826335Speter for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 10925583Speter if (timerisset(&p->p_realtimer.it_value)) 11025583Speter timevaladd(&p->p_realtimer.it_value, &delta); 11126335Speter if (p->p_sleepend) 11226335Speter timevaladd(p->p_sleepend, &delta); 11326335Speter } 11425583Speter lease_updatetime(delta.tv_sec); 11525583Speter splx(s); 11625583Speter resettodr(); 11725583Speter return (0); 11825583Speter} 11925583Speter 12012221Sbde#ifndef _SYS_SYSPROTO_H_ 12125583Speterstruct clock_gettime_args { 12225583Speter clockid_t clock_id; 12325583Speter struct timespec *tp; 12425583Speter}; 12525583Speter#endif 12625656Speter 12725583Speter/* ARGSUSED */ 12825583Speterint 12930994Sphkclock_gettime(p, uap) 13025583Speter struct proc *p; 13125583Speter struct clock_gettime_args *uap; 13225583Speter{ 13325583Speter struct timespec ats; 13425583Speter 13525656Speter if (SCARG(uap, clock_id) != CLOCK_REALTIME) 13625583Speter return (EINVAL); 13733690Sphk nanotime(&ats); 13825656Speter return (copyout(&ats, SCARG(uap, tp), sizeof(ats))); 13925583Speter} 14025583Speter 14125583Speter#ifndef _SYS_SYSPROTO_H_ 14225583Speterstruct clock_settime_args { 14325583Speter clockid_t clock_id; 14425583Speter const struct timespec *tp; 14525583Speter}; 14625583Speter#endif 14725656Speter 14825583Speter/* ARGSUSED */ 14925583Speterint 15030994Sphkclock_settime(p, uap) 15125583Speter struct proc *p; 15225583Speter struct clock_settime_args *uap; 15325583Speter{ 15425583Speter struct timeval atv; 15525583Speter struct timespec ats; 15625583Speter int error; 15725583Speter 15825583Speter if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 15925583Speter return (error); 16025656Speter if (SCARG(uap, clock_id) != CLOCK_REALTIME) 16125583Speter return (EINVAL); 16225583Speter if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0) 16325583Speter return (error); 16427855Sbde if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000) 16525656Speter return (EINVAL); 16634901Sphk /* XXX Don't convert nsec->usec and back */ 16725583Speter TIMESPEC_TO_TIMEVAL(&atv, &ats); 16825583Speter if ((error = settime(&atv))) 16925583Speter return (error); 17025656Speter return (0); 17125583Speter} 17225583Speter 17325583Speter#ifndef _SYS_SYSPROTO_H_ 17425583Speterstruct clock_getres_args { 17525583Speter clockid_t clock_id; 17625583Speter struct timespec *tp; 17725583Speter}; 17825583Speter#endif 17925656Speter 18025583Speterint 18130994Sphkclock_getres(p, uap) 18225583Speter struct proc *p; 18325583Speter struct clock_getres_args *uap; 18425583Speter{ 18525583Speter struct timespec ts; 18625656Speter int error; 18725583Speter 18825656Speter if (SCARG(uap, clock_id) != CLOCK_REALTIME) 18925583Speter return (EINVAL); 19025656Speter error = 0; 19125583Speter if (SCARG(uap, tp)) { 19225583Speter ts.tv_sec = 0; 19333690Sphk ts.tv_nsec = 1000000000 / timecounter->frequency; 19425656Speter error = copyout(&ts, SCARG(uap, tp), sizeof(ts)); 19525583Speter } 19625656Speter return (error); 19725583Speter} 19825583Speter 19926335Speterstatic int nanowait; 20025656Speter 20126335Speterstatic int 20226335Speternanosleep1(p, rqt, rmt) 20325583Speter struct proc *p; 20426335Speter struct timespec *rqt, *rmt; 20525583Speter{ 20628171Sache struct timeval atv, utv, rtv; 20728171Sache int error, s, timo, i, n; 20825583Speter 20928773Sbde if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000) 21025656Speter return (EINVAL); 21128773Sbde if (rqt->tv_sec < 0 || rqt->tv_sec == 0 && rqt->tv_nsec == 0) 21228773Sbde return (0); 21326335Speter TIMESPEC_TO_TIMEVAL(&atv, rqt) 21425583Speter 21528171Sache if (itimerfix(&atv)) { 21628171Sache n = atv.tv_sec / 100000000; 21728171Sache rtv = atv; 21828171Sache rtv.tv_sec %= 100000000; 21928171Sache (void)itimerfix(&rtv); 22028171Sache } else 22128171Sache n = 0; 22225583Speter 22328773Sbde for (i = 0, error = EWOULDBLOCK; i <= n && error == EWOULDBLOCK; i++) { 22428171Sache if (n > 0) { 22528171Sache if (i == n) 22628171Sache atv = rtv; 22728171Sache else { 22828171Sache atv.tv_sec = 100000000; 22928171Sache atv.tv_usec = 0; 23028171Sache } 23128171Sache } 23234961Sphk timo = tvtohz(&atv); 23328171Sache 23428171Sache p->p_sleepend = &atv; 23528171Sache error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", timo); 23628171Sache p->p_sleepend = NULL; 23728171Sache if (error == ERESTART) 23828171Sache error = EINTR; 23928171Sache if (rmt != NULL && (i == n || error != EWOULDBLOCK)) { 24028171Sache /*- 24128171Sache * XXX this is unnecessary and possibly wrong if the timeout 24228171Sache * expired. Then the remaining time should be zero. If the 24328171Sache * calculation gives a nonzero value, then we have a bug. 24428171Sache * (1) if settimeofday() was called, then the calculation is 24528171Sache * probably wrong, since `time' has probably become 24628171Sache * inconsistent with the ending time `atv'. 24728171Sache * XXX (1) should be fixed now with p->p_sleepend; 24828171Sache * (2) otherwise, our calculation of `timo' was wrong, perhaps 24928171Sache * due to `tick' being wrong when hzto() was called or 25028171Sache * changing afterwards (it can be wrong or change due to 25128171Sache * hzto() not knowing about adjtime(2) or tickadj(8)). 25228171Sache * Then we should be sleeping again instead instead of 25328171Sache * returning. Rounding up in hzto() probably fixes this 25428171Sache * problem for small timeouts, but the absolute error may 25528171Sache * be large for large timeouts. 25628171Sache */ 25734961Sphk getmicrotime(&utv); 25830606Sache if (i != n) { 25930606Sache atv.tv_sec += (n - i - 1) * 100000000; 26030606Sache timevaladd(&atv, &rtv); 26130606Sache } 26228171Sache timevalsub(&atv, &utv); 26328171Sache if (atv.tv_sec < 0) 26428171Sache timerclear(&atv); 26528171Sache TIMEVAL_TO_TIMESPEC(&atv, rmt); 26628171Sache } 26726335Speter } 26828171Sache return (error == EWOULDBLOCK ? 0 : error); 26926335Speter} 27025583Speter 27126335Speter#ifndef _SYS_SYSPROTO_H_ 27226335Speterstruct nanosleep_args { 27326335Speter struct timespec *rqtp; 27426335Speter struct timespec *rmtp; 27526335Speter}; 27626335Speter#endif 27726335Speter 27826335Speter/* ARGSUSED */ 27926335Speterint 28030994Sphknanosleep(p, uap) 28126335Speter struct proc *p; 28226335Speter struct nanosleep_args *uap; 28326335Speter{ 28426335Speter struct timespec rmt, rqt; 28526335Speter int error, error2; 28626335Speter 28726335Speter error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt)); 28826335Speter if (error) 28926335Speter return (error); 29026336Speter if (SCARG(uap, rmtp)) 29126336Speter if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE)) 29226336Speter return (EFAULT); 29326335Speter error = nanosleep1(p, &rqt, &rmt); 29426335Speter if (SCARG(uap, rmtp)) { 29525656Speter error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt)); 29626335Speter if (error2) /* XXX shouldn't happen, did useracc() above */ 29725656Speter return (error2); 29825583Speter } 29925656Speter return (error); 30025583Speter} 30125583Speter 30226335Speter#ifndef _SYS_SYSPROTO_H_ 30326335Speterstruct signanosleep_args { 30426335Speter struct timespec *rqtp; 30526335Speter struct timespec *rmtp; 30626335Speter sigset_t *mask; 30726335Speter}; 30826335Speter#endif 30925583Speter 31026335Speter/* ARGSUSED */ 31126335Speterint 31230994Sphksignanosleep(p, uap) 31326335Speter struct proc *p; 31426335Speter struct signanosleep_args *uap; 31526335Speter{ 31626335Speter struct timespec rmt, rqt; 31726335Speter int error, error2; 31826335Speter sigset_t mask; 31926335Speter 32026335Speter error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt)); 32126335Speter if (error) 32226335Speter return (error); 32326336Speter if (SCARG(uap, rmtp)) 32426336Speter if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE)) 32526336Speter return (EFAULT); 32626335Speter error = copyin(SCARG(uap, mask), &mask, sizeof(mask)); 32726335Speter if (error) 32826335Speter return (error); 32926335Speter 33030440Speter /* change mask for sleep */ 33126335Speter p->p_sigmask = mask &~ sigcantmask; 33226335Speter 33326335Speter error = nanosleep1(p, &rqt, &rmt); 33426335Speter 33526335Speter if (SCARG(uap, rmtp)) { 33626335Speter error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt)); 33726335Speter if (error2) /* XXX shouldn't happen, did useracc() above */ 33826335Speter return (error2); 33926335Speter } 34026335Speter return (error); 34126335Speter} 34226335Speter 34325583Speter#ifndef _SYS_SYSPROTO_H_ 3441541Srgrimesstruct gettimeofday_args { 3451541Srgrimes struct timeval *tp; 3461541Srgrimes struct timezone *tzp; 3471541Srgrimes}; 34812221Sbde#endif 3491541Srgrimes/* ARGSUSED */ 3501549Srgrimesint 35130994Sphkgettimeofday(p, uap) 3521541Srgrimes struct proc *p; 3531541Srgrimes register struct gettimeofday_args *uap; 3541541Srgrimes{ 3551541Srgrimes struct timeval atv; 3561541Srgrimes int error = 0; 3571541Srgrimes 3581541Srgrimes if (uap->tp) { 3591541Srgrimes microtime(&atv); 3603098Sphk if ((error = copyout((caddr_t)&atv, (caddr_t)uap->tp, 3613098Sphk sizeof (atv)))) 3621541Srgrimes return (error); 3631541Srgrimes } 3641541Srgrimes if (uap->tzp) 3651541Srgrimes error = copyout((caddr_t)&tz, (caddr_t)uap->tzp, 3661541Srgrimes sizeof (tz)); 3671541Srgrimes return (error); 3681541Srgrimes} 3691541Srgrimes 37012221Sbde#ifndef _SYS_SYSPROTO_H_ 3711541Srgrimesstruct settimeofday_args { 3721541Srgrimes struct timeval *tv; 3731541Srgrimes struct timezone *tzp; 3741541Srgrimes}; 37512221Sbde#endif 3761541Srgrimes/* ARGSUSED */ 3771549Srgrimesint 37830994Sphksettimeofday(p, uap) 3791541Srgrimes struct proc *p; 3801541Srgrimes struct settimeofday_args *uap; 3811541Srgrimes{ 38225656Speter struct timeval atv; 3831541Srgrimes struct timezone atz; 38425656Speter int error; 3851541Srgrimes 3863098Sphk if ((error = suser(p->p_ucred, &p->p_acflag))) 3871541Srgrimes return (error); 3881541Srgrimes /* Verify all parameters before changing time. */ 38925656Speter if (uap->tv) { 39025656Speter if ((error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 39125656Speter sizeof(atv)))) 39225656Speter return (error); 39325656Speter if (atv.tv_usec < 0 || atv.tv_usec >= 1000000) 39425656Speter return (EINVAL); 39525656Speter } 3961541Srgrimes if (uap->tzp && 3971541Srgrimes (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz)))) 3981541Srgrimes return (error); 39925583Speter if (uap->tv && (error = settime(&atv))) 40025583Speter return (error); 4011541Srgrimes if (uap->tzp) 4021541Srgrimes tz = atz; 4031541Srgrimes return (0); 4041541Srgrimes} 4051541Srgrimes 4061541Srgrimesint tickdelta; /* current clock skew, us. per tick */ 4071541Srgrimeslong timedelta; /* unapplied time correction, us. */ 40812819Sphkstatic long bigadj = 1000000; /* use 10x skew above bigadj us. */ 4091541Srgrimes 41012221Sbde#ifndef _SYS_SYSPROTO_H_ 4111541Srgrimesstruct adjtime_args { 4121541Srgrimes struct timeval *delta; 4131541Srgrimes struct timeval *olddelta; 4141541Srgrimes}; 41512221Sbde#endif 4161541Srgrimes/* ARGSUSED */ 4171549Srgrimesint 41830994Sphkadjtime(p, uap) 4191541Srgrimes struct proc *p; 4201541Srgrimes register struct adjtime_args *uap; 4211541Srgrimes{ 4221541Srgrimes struct timeval atv; 4231541Srgrimes register long ndelta, ntickdelta, odelta; 4241541Srgrimes int s, error; 4251541Srgrimes 4263098Sphk if ((error = suser(p->p_ucred, &p->p_acflag))) 4271541Srgrimes return (error); 4283098Sphk if ((error = 4293098Sphk copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval)))) 4301541Srgrimes return (error); 4311541Srgrimes 4321541Srgrimes /* 4331541Srgrimes * Compute the total correction and the rate at which to apply it. 4341541Srgrimes * Round the adjustment down to a whole multiple of the per-tick 4351541Srgrimes * delta, so that after some number of incremental changes in 4361541Srgrimes * hardclock(), tickdelta will become zero, lest the correction 4371541Srgrimes * overshoot and start taking us away from the desired final time. 4381541Srgrimes */ 4391541Srgrimes ndelta = atv.tv_sec * 1000000 + atv.tv_usec; 44017123Sbde if (ndelta > bigadj || ndelta < -bigadj) 4411541Srgrimes ntickdelta = 10 * tickadj; 4421541Srgrimes else 4431541Srgrimes ntickdelta = tickadj; 4441541Srgrimes if (ndelta % ntickdelta) 4451541Srgrimes ndelta = ndelta / ntickdelta * ntickdelta; 4461541Srgrimes 4471541Srgrimes /* 4481541Srgrimes * To make hardclock()'s job easier, make the per-tick delta negative 4491541Srgrimes * if we want time to run slower; then hardclock can simply compute 4501541Srgrimes * tick + tickdelta, and subtract tickdelta from timedelta. 4511541Srgrimes */ 4521541Srgrimes if (ndelta < 0) 4531541Srgrimes ntickdelta = -ntickdelta; 4541541Srgrimes s = splclock(); 4551541Srgrimes odelta = timedelta; 4561541Srgrimes timedelta = ndelta; 4571541Srgrimes tickdelta = ntickdelta; 4581541Srgrimes splx(s); 4591541Srgrimes 4601541Srgrimes if (uap->olddelta) { 4611541Srgrimes atv.tv_sec = odelta / 1000000; 4621541Srgrimes atv.tv_usec = odelta % 1000000; 4631541Srgrimes (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta, 4641541Srgrimes sizeof(struct timeval)); 4651541Srgrimes } 4661541Srgrimes return (0); 4671541Srgrimes} 4681541Srgrimes 4691541Srgrimes/* 4701541Srgrimes * Get value of an interval timer. The process virtual and 4711541Srgrimes * profiling virtual time timers are kept in the p_stats area, since 4721541Srgrimes * they can be swapped out. These are kept internally in the 4731541Srgrimes * way they are specified externally: in time until they expire. 4741541Srgrimes * 4751541Srgrimes * The real time interval timer is kept in the process table slot 4761541Srgrimes * for the process, and its value (it_value) is kept as an 4771541Srgrimes * absolute time rather than as a delta, so that it is easy to keep 4781541Srgrimes * periodic real-time signals from drifting. 4791541Srgrimes * 4801541Srgrimes * Virtual time timers are processed in the hardclock() routine of 4811541Srgrimes * kern_clock.c. The real time timer is processed by a timeout 4821541Srgrimes * routine, called from the softclock() routine. Since a callout 4831541Srgrimes * may be delayed in real time due to interrupt processing in the system, 4841541Srgrimes * it is possible for the real time timeout routine (realitexpire, given below), 4851541Srgrimes * to be delayed in real time past when it is supposed to occur. It 4861541Srgrimes * does not suffice, therefore, to reload the real timer .it_value from the 4871541Srgrimes * real time timers .it_interval. Rather, we compute the next time in 4881541Srgrimes * absolute time the timer should go off. 4891541Srgrimes */ 49012221Sbde#ifndef _SYS_SYSPROTO_H_ 4911541Srgrimesstruct getitimer_args { 4921541Srgrimes u_int which; 4931541Srgrimes struct itimerval *itv; 4941541Srgrimes}; 49512221Sbde#endif 4961541Srgrimes/* ARGSUSED */ 4971549Srgrimesint 49830994Sphkgetitimer(p, uap) 4991541Srgrimes struct proc *p; 5001541Srgrimes register struct getitimer_args *uap; 5011541Srgrimes{ 50234961Sphk struct timeval ctv; 5031541Srgrimes struct itimerval aitv; 5041541Srgrimes int s; 5051541Srgrimes 5061541Srgrimes if (uap->which > ITIMER_PROF) 5071541Srgrimes return (EINVAL); 50834961Sphk s = splclock(); /* XXX still needed ? */ 5091541Srgrimes if (uap->which == ITIMER_REAL) { 5101541Srgrimes /* 5111541Srgrimes * Convert from absoulte to relative time in .it_value 5121541Srgrimes * part of real time timer. If time for real time timer 5131541Srgrimes * has passed return 0, else return difference between 5141541Srgrimes * current time and time for the timer to go off. 5151541Srgrimes */ 5161541Srgrimes aitv = p->p_realtimer; 51734961Sphk if (timerisset(&aitv.it_value)) { 51834961Sphk getmicrotime(&ctv); 51934961Sphk if (timercmp(&aitv.it_value, &ctv, <)) 5201541Srgrimes timerclear(&aitv.it_value); 5211541Srgrimes else 52234961Sphk timevalsub(&aitv.it_value, &ctv); 52334961Sphk } 5241541Srgrimes } else 5251541Srgrimes aitv = p->p_stats->p_timer[uap->which]; 5261541Srgrimes splx(s); 5271541Srgrimes return (copyout((caddr_t)&aitv, (caddr_t)uap->itv, 5281541Srgrimes sizeof (struct itimerval))); 5291541Srgrimes} 5301541Srgrimes 53112221Sbde#ifndef _SYS_SYSPROTO_H_ 5321541Srgrimesstruct setitimer_args { 5331541Srgrimes u_int which; 5341541Srgrimes struct itimerval *itv, *oitv; 5351541Srgrimes}; 53612221Sbde#endif 5371541Srgrimes/* ARGSUSED */ 5381549Srgrimesint 53930994Sphksetitimer(p, uap) 5401541Srgrimes struct proc *p; 5411541Srgrimes register struct setitimer_args *uap; 5421541Srgrimes{ 5431541Srgrimes struct itimerval aitv; 54434961Sphk struct timeval ctv; 5451541Srgrimes register struct itimerval *itvp; 5461541Srgrimes int s, error; 5471541Srgrimes 5481541Srgrimes if (uap->which > ITIMER_PROF) 5491541Srgrimes return (EINVAL); 5501541Srgrimes itvp = uap->itv; 5511541Srgrimes if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv, 5521541Srgrimes sizeof(struct itimerval)))) 5531541Srgrimes return (error); 55412381Sbde if ((uap->itv = uap->oitv) && 55530994Sphk (error = getitimer(p, (struct getitimer_args *)uap))) 5561541Srgrimes return (error); 5571541Srgrimes if (itvp == 0) 5581541Srgrimes return (0); 55928213Sache if (itimerfix(&aitv.it_value)) 5601541Srgrimes return (EINVAL); 56128213Sache if (!timerisset(&aitv.it_value)) 56228213Sache timerclear(&aitv.it_interval); 56328213Sache else if (itimerfix(&aitv.it_interval)) 56428213Sache return (EINVAL); 56534961Sphk s = splclock(); /* XXX: still needed ? */ 5661541Srgrimes if (uap->which == ITIMER_REAL) { 56729680Sgibbs if (timerisset(&p->p_realtimer.it_value)) 56829680Sgibbs untimeout(realitexpire, (caddr_t)p, p->p_ithandle); 5691541Srgrimes if (timerisset(&aitv.it_value)) { 57034961Sphk getmicrotime(&ctv); 57134961Sphk timevaladd(&aitv.it_value, &ctv); 57229680Sgibbs p->p_ithandle = timeout(realitexpire, (caddr_t)p, 57329680Sgibbs hzto(&aitv.it_value)); 5741541Srgrimes } 5751541Srgrimes p->p_realtimer = aitv; 5761541Srgrimes } else 5771541Srgrimes p->p_stats->p_timer[uap->which] = aitv; 5781541Srgrimes splx(s); 5791541Srgrimes return (0); 5801541Srgrimes} 5811541Srgrimes 5821541Srgrimes/* 5831541Srgrimes * Real interval timer expired: 5841541Srgrimes * send process whose timer expired an alarm signal. 5851541Srgrimes * If time is not set up to reload, then just return. 5861541Srgrimes * Else compute next time timer should go off which is > current time. 5871541Srgrimes * This is where delay in processing this timeout causes multiple 5881541Srgrimes * SIGALRM calls to be compressed into one. 5899327Sbde * hzto() always adds 1 to allow for the time until the next clock 5909327Sbde * interrupt being strictly less than 1 clock tick, but we don't want 5919327Sbde * that here since we want to appear to be in sync with the clock 5929327Sbde * interrupt even when we're delayed. 5931541Srgrimes */ 5941541Srgrimesvoid 5951541Srgrimesrealitexpire(arg) 5961541Srgrimes void *arg; 5971541Srgrimes{ 5981541Srgrimes register struct proc *p; 59934961Sphk struct timeval ctv; 6001541Srgrimes int s; 6011541Srgrimes 6021541Srgrimes p = (struct proc *)arg; 6031541Srgrimes psignal(p, SIGALRM); 6041541Srgrimes if (!timerisset(&p->p_realtimer.it_interval)) { 6051541Srgrimes timerclear(&p->p_realtimer.it_value); 6061541Srgrimes return; 6071541Srgrimes } 6081541Srgrimes for (;;) { 60934961Sphk s = splclock(); /* XXX: still neeeded ? */ 6101541Srgrimes timevaladd(&p->p_realtimer.it_value, 6111541Srgrimes &p->p_realtimer.it_interval); 61234961Sphk getmicrotime(&ctv); 61334961Sphk if (timercmp(&p->p_realtimer.it_value, &ctv, >)) { 61429680Sgibbs p->p_ithandle = 61529680Sgibbs timeout(realitexpire, (caddr_t)p, 61629680Sgibbs hzto(&p->p_realtimer.it_value) - 1); 6171541Srgrimes splx(s); 6181541Srgrimes return; 6191541Srgrimes } 6201541Srgrimes splx(s); 6211541Srgrimes } 6221541Srgrimes} 6231541Srgrimes 6241541Srgrimes/* 6251541Srgrimes * Check that a proposed value to load into the .it_value or 6261541Srgrimes * .it_interval part of an interval timer is acceptable, and 6271541Srgrimes * fix it to have at least minimal value (i.e. if it is less 6281541Srgrimes * than the resolution of the clock, round it up.) 6291541Srgrimes */ 6301549Srgrimesint 6311541Srgrimesitimerfix(tv) 6321541Srgrimes struct timeval *tv; 6331541Srgrimes{ 6341541Srgrimes 6351541Srgrimes if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 6361541Srgrimes tv->tv_usec < 0 || tv->tv_usec >= 1000000) 6371541Srgrimes return (EINVAL); 6381541Srgrimes if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 6391541Srgrimes tv->tv_usec = tick; 6401541Srgrimes return (0); 6411541Srgrimes} 6421541Srgrimes 6431541Srgrimes/* 6441541Srgrimes * Decrement an interval timer by a specified number 6451541Srgrimes * of microseconds, which must be less than a second, 6461541Srgrimes * i.e. < 1000000. If the timer expires, then reload 6471541Srgrimes * it. In this case, carry over (usec - old value) to 6481541Srgrimes * reduce the value reloaded into the timer so that 6491541Srgrimes * the timer does not drift. This routine assumes 6501541Srgrimes * that it is called in a context where the timers 6511541Srgrimes * on which it is operating cannot change in value. 6521541Srgrimes */ 6531549Srgrimesint 6541541Srgrimesitimerdecr(itp, usec) 6551541Srgrimes register struct itimerval *itp; 6561541Srgrimes int usec; 6571541Srgrimes{ 6581541Srgrimes 6591541Srgrimes if (itp->it_value.tv_usec < usec) { 6601541Srgrimes if (itp->it_value.tv_sec == 0) { 6611541Srgrimes /* expired, and already in next interval */ 6621541Srgrimes usec -= itp->it_value.tv_usec; 6631541Srgrimes goto expire; 6641541Srgrimes } 6651541Srgrimes itp->it_value.tv_usec += 1000000; 6661541Srgrimes itp->it_value.tv_sec--; 6671541Srgrimes } 6681541Srgrimes itp->it_value.tv_usec -= usec; 6691541Srgrimes usec = 0; 6701541Srgrimes if (timerisset(&itp->it_value)) 6711541Srgrimes return (1); 6721541Srgrimes /* expired, exactly at end of interval */ 6731541Srgrimesexpire: 6741541Srgrimes if (timerisset(&itp->it_interval)) { 6751541Srgrimes itp->it_value = itp->it_interval; 6761541Srgrimes itp->it_value.tv_usec -= usec; 6771541Srgrimes if (itp->it_value.tv_usec < 0) { 6781541Srgrimes itp->it_value.tv_usec += 1000000; 6791541Srgrimes itp->it_value.tv_sec--; 6801541Srgrimes } 6811541Srgrimes } else 6821541Srgrimes itp->it_value.tv_usec = 0; /* sec is already 0 */ 6831541Srgrimes return (0); 6841541Srgrimes} 6851541Srgrimes 6861541Srgrimes/* 6871541Srgrimes * Add and subtract routines for timevals. 6881541Srgrimes * N.B.: subtract routine doesn't deal with 6891541Srgrimes * results which are before the beginning, 6901541Srgrimes * it just gets very confused in this case. 6911541Srgrimes * Caveat emptor. 6921541Srgrimes */ 6931549Srgrimesvoid 6941541Srgrimestimevaladd(t1, t2) 6951541Srgrimes struct timeval *t1, *t2; 6961541Srgrimes{ 6971541Srgrimes 6981541Srgrimes t1->tv_sec += t2->tv_sec; 6991541Srgrimes t1->tv_usec += t2->tv_usec; 7001541Srgrimes timevalfix(t1); 7011541Srgrimes} 7021541Srgrimes 7031549Srgrimesvoid 7041541Srgrimestimevalsub(t1, t2) 7051541Srgrimes struct timeval *t1, *t2; 7061541Srgrimes{ 7071541Srgrimes 7081541Srgrimes t1->tv_sec -= t2->tv_sec; 7091541Srgrimes t1->tv_usec -= t2->tv_usec; 7101541Srgrimes timevalfix(t1); 7111541Srgrimes} 7121541Srgrimes 71312819Sphkstatic void 7141541Srgrimestimevalfix(t1) 7151541Srgrimes struct timeval *t1; 7161541Srgrimes{ 7171541Srgrimes 7181541Srgrimes if (t1->tv_usec < 0) { 7191541Srgrimes t1->tv_sec--; 7201541Srgrimes t1->tv_usec += 1000000; 7211541Srgrimes } 7221541Srgrimes if (t1->tv_usec >= 1000000) { 7231541Srgrimes t1->tv_sec++; 7241541Srgrimes t1->tv_usec -= 1000000; 7251541Srgrimes } 7261541Srgrimes} 727