kern_time.c revision 8876
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 348876Srgrimes * $Id: kern_time.c,v 1.7 1995/03/16 18:12:38 bde Exp $ 351541Srgrimes */ 361541Srgrimes 371541Srgrimes#include <sys/param.h> 381541Srgrimes#include <sys/resourcevar.h> 393308Sphk#include <sys/signalvar.h> 401541Srgrimes#include <sys/kernel.h> 411541Srgrimes#include <sys/systm.h> 421541Srgrimes#include <sys/proc.h> 431541Srgrimes#include <sys/vnode.h> 441541Srgrimes 451541Srgrimes#include <machine/cpu.h> 461541Srgrimes 478876Srgrimes/* 481541Srgrimes * Time of day and interval timer support. 491541Srgrimes * 501541Srgrimes * These routines provide the kernel entry points to get and set 511541Srgrimes * the time-of-day and per-process interval timers. Subroutines 521541Srgrimes * here provide support for adding and subtracting timeval structures 531541Srgrimes * and decrementing interval timers, optionally reloading the interval 541541Srgrimes * timers when they expire. 551541Srgrimes */ 561541Srgrimes 571541Srgrimesstruct gettimeofday_args { 581541Srgrimes struct timeval *tp; 591541Srgrimes struct timezone *tzp; 601541Srgrimes}; 611541Srgrimes/* ARGSUSED */ 621549Srgrimesint 631541Srgrimesgettimeofday(p, uap, retval) 641541Srgrimes struct proc *p; 651541Srgrimes register struct gettimeofday_args *uap; 661541Srgrimes int *retval; 671541Srgrimes{ 681541Srgrimes struct timeval atv; 691541Srgrimes int error = 0; 701541Srgrimes 711541Srgrimes if (uap->tp) { 721541Srgrimes microtime(&atv); 733098Sphk if ((error = copyout((caddr_t)&atv, (caddr_t)uap->tp, 743098Sphk sizeof (atv)))) 751541Srgrimes return (error); 761541Srgrimes } 771541Srgrimes if (uap->tzp) 781541Srgrimes error = copyout((caddr_t)&tz, (caddr_t)uap->tzp, 791541Srgrimes sizeof (tz)); 801541Srgrimes return (error); 811541Srgrimes} 821541Srgrimes 831541Srgrimesstruct settimeofday_args { 841541Srgrimes struct timeval *tv; 851541Srgrimes struct timezone *tzp; 861541Srgrimes}; 871541Srgrimes/* ARGSUSED */ 881549Srgrimesint 891541Srgrimessettimeofday(p, uap, retval) 901541Srgrimes struct proc *p; 911541Srgrimes struct settimeofday_args *uap; 921541Srgrimes int *retval; 931541Srgrimes{ 941541Srgrimes struct timeval atv, delta; 951541Srgrimes struct timezone atz; 961541Srgrimes int error, s; 971541Srgrimes 983098Sphk if ((error = suser(p->p_ucred, &p->p_acflag))) 991541Srgrimes return (error); 1001541Srgrimes /* Verify all parameters before changing time. */ 1011541Srgrimes if (uap->tv && 1021541Srgrimes (error = copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof(atv)))) 1031541Srgrimes return (error); 1041541Srgrimes if (uap->tzp && 1051541Srgrimes (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz)))) 1061541Srgrimes return (error); 1071541Srgrimes if (uap->tv) { 1081541Srgrimes /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 1091541Srgrimes s = splclock(); 1101541Srgrimes /* nb. delta.tv_usec may be < 0, but this is OK here */ 1111541Srgrimes delta.tv_sec = atv.tv_sec - time.tv_sec; 1121541Srgrimes delta.tv_usec = atv.tv_usec - time.tv_usec; 1131541Srgrimes time = atv; 1141541Srgrimes (void) splsoftclock(); 1151541Srgrimes timevaladd(&boottime, &delta); 1161541Srgrimes timevalfix(&boottime); 1171541Srgrimes timevaladd(&runtime, &delta); 1181541Srgrimes timevalfix(&runtime); 1191541Srgrimes LEASE_UPDATETIME(delta.tv_sec); 1201541Srgrimes splx(s); 1211541Srgrimes resettodr(); 1221541Srgrimes } 1231541Srgrimes if (uap->tzp) 1241541Srgrimes tz = atz; 1251541Srgrimes return (0); 1261541Srgrimes} 1271541Srgrimes 1281541Srgrimesextern int tickadj; /* "standard" clock skew, us./tick */ 1291541Srgrimesint tickdelta; /* current clock skew, us. per tick */ 1301541Srgrimeslong timedelta; /* unapplied time correction, us. */ 1311541Srgrimeslong bigadj = 1000000; /* use 10x skew above bigadj us. */ 1321541Srgrimes 1331541Srgrimesstruct adjtime_args { 1341541Srgrimes struct timeval *delta; 1351541Srgrimes struct timeval *olddelta; 1361541Srgrimes}; 1371541Srgrimes/* ARGSUSED */ 1381549Srgrimesint 1391541Srgrimesadjtime(p, uap, retval) 1401541Srgrimes struct proc *p; 1411541Srgrimes register struct adjtime_args *uap; 1421541Srgrimes int *retval; 1431541Srgrimes{ 1441541Srgrimes struct timeval atv; 1451541Srgrimes register long ndelta, ntickdelta, odelta; 1461541Srgrimes int s, error; 1471541Srgrimes 1483098Sphk if ((error = suser(p->p_ucred, &p->p_acflag))) 1491541Srgrimes return (error); 1503098Sphk if ((error = 1513098Sphk copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval)))) 1521541Srgrimes return (error); 1531541Srgrimes 1541541Srgrimes /* 1551541Srgrimes * Compute the total correction and the rate at which to apply it. 1561541Srgrimes * Round the adjustment down to a whole multiple of the per-tick 1571541Srgrimes * delta, so that after some number of incremental changes in 1581541Srgrimes * hardclock(), tickdelta will become zero, lest the correction 1591541Srgrimes * overshoot and start taking us away from the desired final time. 1601541Srgrimes */ 1611541Srgrimes ndelta = atv.tv_sec * 1000000 + atv.tv_usec; 1621541Srgrimes if (ndelta > bigadj) 1631541Srgrimes ntickdelta = 10 * tickadj; 1641541Srgrimes else 1651541Srgrimes ntickdelta = tickadj; 1661541Srgrimes if (ndelta % ntickdelta) 1671541Srgrimes ndelta = ndelta / ntickdelta * ntickdelta; 1681541Srgrimes 1691541Srgrimes /* 1701541Srgrimes * To make hardclock()'s job easier, make the per-tick delta negative 1711541Srgrimes * if we want time to run slower; then hardclock can simply compute 1721541Srgrimes * tick + tickdelta, and subtract tickdelta from timedelta. 1731541Srgrimes */ 1741541Srgrimes if (ndelta < 0) 1751541Srgrimes ntickdelta = -ntickdelta; 1761541Srgrimes s = splclock(); 1771541Srgrimes odelta = timedelta; 1781541Srgrimes timedelta = ndelta; 1791541Srgrimes tickdelta = ntickdelta; 1801541Srgrimes splx(s); 1811541Srgrimes 1821541Srgrimes if (uap->olddelta) { 1831541Srgrimes atv.tv_sec = odelta / 1000000; 1841541Srgrimes atv.tv_usec = odelta % 1000000; 1851541Srgrimes (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta, 1861541Srgrimes sizeof(struct timeval)); 1871541Srgrimes } 1881541Srgrimes return (0); 1891541Srgrimes} 1901541Srgrimes 1911541Srgrimes/* 1921541Srgrimes * Get value of an interval timer. The process virtual and 1931541Srgrimes * profiling virtual time timers are kept in the p_stats area, since 1941541Srgrimes * they can be swapped out. These are kept internally in the 1951541Srgrimes * way they are specified externally: in time until they expire. 1961541Srgrimes * 1971541Srgrimes * The real time interval timer is kept in the process table slot 1981541Srgrimes * for the process, and its value (it_value) is kept as an 1991541Srgrimes * absolute time rather than as a delta, so that it is easy to keep 2001541Srgrimes * periodic real-time signals from drifting. 2011541Srgrimes * 2021541Srgrimes * Virtual time timers are processed in the hardclock() routine of 2031541Srgrimes * kern_clock.c. The real time timer is processed by a timeout 2041541Srgrimes * routine, called from the softclock() routine. Since a callout 2051541Srgrimes * may be delayed in real time due to interrupt processing in the system, 2061541Srgrimes * it is possible for the real time timeout routine (realitexpire, given below), 2071541Srgrimes * to be delayed in real time past when it is supposed to occur. It 2081541Srgrimes * does not suffice, therefore, to reload the real timer .it_value from the 2091541Srgrimes * real time timers .it_interval. Rather, we compute the next time in 2101541Srgrimes * absolute time the timer should go off. 2111541Srgrimes */ 2121541Srgrimesstruct getitimer_args { 2131541Srgrimes u_int which; 2141541Srgrimes struct itimerval *itv; 2151541Srgrimes}; 2161541Srgrimes/* ARGSUSED */ 2171549Srgrimesint 2181541Srgrimesgetitimer(p, uap, retval) 2191541Srgrimes struct proc *p; 2201541Srgrimes register struct getitimer_args *uap; 2211541Srgrimes int *retval; 2221541Srgrimes{ 2231541Srgrimes struct itimerval aitv; 2241541Srgrimes int s; 2251541Srgrimes 2261541Srgrimes if (uap->which > ITIMER_PROF) 2271541Srgrimes return (EINVAL); 2281541Srgrimes s = splclock(); 2291541Srgrimes if (uap->which == ITIMER_REAL) { 2301541Srgrimes /* 2311541Srgrimes * Convert from absoulte to relative time in .it_value 2321541Srgrimes * part of real time timer. If time for real time timer 2331541Srgrimes * has passed return 0, else return difference between 2341541Srgrimes * current time and time for the timer to go off. 2351541Srgrimes */ 2361541Srgrimes aitv = p->p_realtimer; 2371541Srgrimes if (timerisset(&aitv.it_value)) 2381541Srgrimes if (timercmp(&aitv.it_value, &time, <)) 2391541Srgrimes timerclear(&aitv.it_value); 2401541Srgrimes else 2411541Srgrimes timevalsub(&aitv.it_value, 2421541Srgrimes (struct timeval *)&time); 2431541Srgrimes } else 2441541Srgrimes aitv = p->p_stats->p_timer[uap->which]; 2451541Srgrimes splx(s); 2461541Srgrimes return (copyout((caddr_t)&aitv, (caddr_t)uap->itv, 2471541Srgrimes sizeof (struct itimerval))); 2481541Srgrimes} 2491541Srgrimes 2501541Srgrimesstruct setitimer_args { 2511541Srgrimes u_int which; 2521541Srgrimes struct itimerval *itv, *oitv; 2531541Srgrimes}; 2541541Srgrimes/* ARGSUSED */ 2551549Srgrimesint 2561541Srgrimessetitimer(p, uap, retval) 2571541Srgrimes struct proc *p; 2581541Srgrimes register struct setitimer_args *uap; 2591541Srgrimes int *retval; 2601541Srgrimes{ 2611541Srgrimes struct itimerval aitv; 2621541Srgrimes register struct itimerval *itvp; 2631541Srgrimes int s, error; 2641541Srgrimes 2651541Srgrimes if (uap->which > ITIMER_PROF) 2661541Srgrimes return (EINVAL); 2671541Srgrimes itvp = uap->itv; 2681541Srgrimes if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv, 2691541Srgrimes sizeof(struct itimerval)))) 2701541Srgrimes return (error); 2711541Srgrimes if ((uap->itv = uap->oitv) && (error = getitimer(p, uap, retval))) 2721541Srgrimes return (error); 2731541Srgrimes if (itvp == 0) 2741541Srgrimes return (0); 2751541Srgrimes if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) 2761541Srgrimes return (EINVAL); 2771541Srgrimes s = splclock(); 2781541Srgrimes if (uap->which == ITIMER_REAL) { 2791541Srgrimes untimeout(realitexpire, (caddr_t)p); 2801541Srgrimes if (timerisset(&aitv.it_value)) { 2811541Srgrimes timevaladd(&aitv.it_value, (struct timeval *)&time); 2821541Srgrimes timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value)); 2831541Srgrimes } 2841541Srgrimes p->p_realtimer = aitv; 2851541Srgrimes } else 2861541Srgrimes p->p_stats->p_timer[uap->which] = aitv; 2871541Srgrimes splx(s); 2881541Srgrimes return (0); 2891541Srgrimes} 2901541Srgrimes 2911541Srgrimes/* 2921541Srgrimes * Real interval timer expired: 2931541Srgrimes * send process whose timer expired an alarm signal. 2941541Srgrimes * If time is not set up to reload, then just return. 2951541Srgrimes * Else compute next time timer should go off which is > current time. 2961541Srgrimes * This is where delay in processing this timeout causes multiple 2971541Srgrimes * SIGALRM calls to be compressed into one. 2981541Srgrimes */ 2991541Srgrimesvoid 3001541Srgrimesrealitexpire(arg) 3011541Srgrimes void *arg; 3021541Srgrimes{ 3031541Srgrimes register struct proc *p; 3041541Srgrimes int s; 3051541Srgrimes 3061541Srgrimes p = (struct proc *)arg; 3071541Srgrimes psignal(p, SIGALRM); 3081541Srgrimes if (!timerisset(&p->p_realtimer.it_interval)) { 3091541Srgrimes timerclear(&p->p_realtimer.it_value); 3101541Srgrimes return; 3111541Srgrimes } 3121541Srgrimes for (;;) { 3131541Srgrimes s = splclock(); 3141541Srgrimes timevaladd(&p->p_realtimer.it_value, 3151541Srgrimes &p->p_realtimer.it_interval); 3161541Srgrimes if (timercmp(&p->p_realtimer.it_value, &time, >)) { 3171541Srgrimes timeout(realitexpire, (caddr_t)p, 3181541Srgrimes hzto(&p->p_realtimer.it_value)); 3191541Srgrimes splx(s); 3201541Srgrimes return; 3211541Srgrimes } 3221541Srgrimes splx(s); 3231541Srgrimes } 3241541Srgrimes} 3251541Srgrimes 3261541Srgrimes/* 3271541Srgrimes * Check that a proposed value to load into the .it_value or 3281541Srgrimes * .it_interval part of an interval timer is acceptable, and 3291541Srgrimes * fix it to have at least minimal value (i.e. if it is less 3301541Srgrimes * than the resolution of the clock, round it up.) 3311541Srgrimes */ 3321549Srgrimesint 3331541Srgrimesitimerfix(tv) 3341541Srgrimes struct timeval *tv; 3351541Srgrimes{ 3361541Srgrimes 3371541Srgrimes if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 3381541Srgrimes tv->tv_usec < 0 || tv->tv_usec >= 1000000) 3391541Srgrimes return (EINVAL); 3401541Srgrimes if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 3411541Srgrimes tv->tv_usec = tick; 3421541Srgrimes return (0); 3431541Srgrimes} 3441541Srgrimes 3451541Srgrimes/* 3461541Srgrimes * Decrement an interval timer by a specified number 3471541Srgrimes * of microseconds, which must be less than a second, 3481541Srgrimes * i.e. < 1000000. If the timer expires, then reload 3491541Srgrimes * it. In this case, carry over (usec - old value) to 3501541Srgrimes * reduce the value reloaded into the timer so that 3511541Srgrimes * the timer does not drift. This routine assumes 3521541Srgrimes * that it is called in a context where the timers 3531541Srgrimes * on which it is operating cannot change in value. 3541541Srgrimes */ 3551549Srgrimesint 3561541Srgrimesitimerdecr(itp, usec) 3571541Srgrimes register struct itimerval *itp; 3581541Srgrimes int usec; 3591541Srgrimes{ 3601541Srgrimes 3611541Srgrimes if (itp->it_value.tv_usec < usec) { 3621541Srgrimes if (itp->it_value.tv_sec == 0) { 3631541Srgrimes /* expired, and already in next interval */ 3641541Srgrimes usec -= itp->it_value.tv_usec; 3651541Srgrimes goto expire; 3661541Srgrimes } 3671541Srgrimes itp->it_value.tv_usec += 1000000; 3681541Srgrimes itp->it_value.tv_sec--; 3691541Srgrimes } 3701541Srgrimes itp->it_value.tv_usec -= usec; 3711541Srgrimes usec = 0; 3721541Srgrimes if (timerisset(&itp->it_value)) 3731541Srgrimes return (1); 3741541Srgrimes /* expired, exactly at end of interval */ 3751541Srgrimesexpire: 3761541Srgrimes if (timerisset(&itp->it_interval)) { 3771541Srgrimes itp->it_value = itp->it_interval; 3781541Srgrimes itp->it_value.tv_usec -= usec; 3791541Srgrimes if (itp->it_value.tv_usec < 0) { 3801541Srgrimes itp->it_value.tv_usec += 1000000; 3811541Srgrimes itp->it_value.tv_sec--; 3821541Srgrimes } 3831541Srgrimes } else 3841541Srgrimes itp->it_value.tv_usec = 0; /* sec is already 0 */ 3851541Srgrimes return (0); 3861541Srgrimes} 3871541Srgrimes 3881541Srgrimes/* 3891541Srgrimes * Add and subtract routines for timevals. 3901541Srgrimes * N.B.: subtract routine doesn't deal with 3911541Srgrimes * results which are before the beginning, 3921541Srgrimes * it just gets very confused in this case. 3931541Srgrimes * Caveat emptor. 3941541Srgrimes */ 3951549Srgrimesvoid 3961541Srgrimestimevaladd(t1, t2) 3971541Srgrimes struct timeval *t1, *t2; 3981541Srgrimes{ 3991541Srgrimes 4001541Srgrimes t1->tv_sec += t2->tv_sec; 4011541Srgrimes t1->tv_usec += t2->tv_usec; 4021541Srgrimes timevalfix(t1); 4031541Srgrimes} 4041541Srgrimes 4051549Srgrimesvoid 4061541Srgrimestimevalsub(t1, t2) 4071541Srgrimes struct timeval *t1, *t2; 4081541Srgrimes{ 4091541Srgrimes 4101541Srgrimes t1->tv_sec -= t2->tv_sec; 4111541Srgrimes t1->tv_usec -= t2->tv_usec; 4121541Srgrimes timevalfix(t1); 4131541Srgrimes} 4141541Srgrimes 4151549Srgrimesvoid 4161541Srgrimestimevalfix(t1) 4171541Srgrimes struct timeval *t1; 4181541Srgrimes{ 4191541Srgrimes 4201541Srgrimes if (t1->tv_usec < 0) { 4211541Srgrimes t1->tv_sec--; 4221541Srgrimes t1->tv_usec += 1000000; 4231541Srgrimes } 4241541Srgrimes if (t1->tv_usec >= 1000000) { 4251541Srgrimes t1->tv_sec++; 4261541Srgrimes t1->tv_usec -= 1000000; 4271541Srgrimes } 4281541Srgrimes} 429