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