123377Smckusick /* 263176Sbostic * Copyright (c) 1982, 1986, 1989, 1993 363176Sbostic * The Regents of the University of California. All rights reserved. 423377Smckusick * 544441Sbostic * %sccs.include.redist.c% 637583Smckusick * 7*67639Smckusick * @(#)kern_time.c 8.2 (Berkeley) 08/10/94 823377Smckusick */ 97424Sroot 1056517Sbostic #include <sys/param.h> 1156517Sbostic #include <sys/resourcevar.h> 1256517Sbostic #include <sys/kernel.h> 1356517Sbostic #include <sys/systm.h> 1456517Sbostic #include <sys/proc.h> 1556517Sbostic #include <sys/vnode.h> 167424Sroot 1756517Sbostic #include <machine/cpu.h> 1829946Skarels 198103Sroot /* 208103Sroot * Time of day and interval timer support. 218146Sroot * 228146Sroot * These routines provide the kernel entry points to get and set 238146Sroot * the time-of-day and per-process interval timers. Subroutines 248146Sroot * here provide support for adding and subtracting timeval structures 258146Sroot * and decrementing interval timers, optionally reloading the interval 268146Sroot * timers when they expire. 278103Sroot */ 288103Sroot 2954927Storek struct gettimeofday_args { 3054927Storek struct timeval *tp; 3154927Storek struct timezone *tzp; 3254927Storek }; 3343392Skarels /* ARGSUSED */ 3443392Skarels gettimeofday(p, uap, retval) 3543392Skarels struct proc *p; 3654927Storek register struct gettimeofday_args *uap; 3743392Skarels int *retval; 3843392Skarels { 398034Sroot struct timeval atv; 4043392Skarels int error = 0; 417500Sroot 4230666Sbostic if (uap->tp) { 4330666Sbostic microtime(&atv); 4443392Skarels if (error = copyout((caddr_t)&atv, (caddr_t)uap->tp, 4543392Skarels sizeof (atv))) 4644405Skarels return (error); 4730666Sbostic } 4830666Sbostic if (uap->tzp) 4943392Skarels error = copyout((caddr_t)&tz, (caddr_t)uap->tzp, 5043392Skarels sizeof (tz)); 5144405Skarels return (error); 527500Sroot } 537500Sroot 5454927Storek struct settimeofday_args { 5554927Storek struct timeval *tv; 5654927Storek struct timezone *tzp; 5754927Storek }; 5845120Sbostic /* ARGSUSED */ 5943392Skarels settimeofday(p, uap, retval) 6043392Skarels struct proc *p; 6154927Storek struct settimeofday_args *uap; 6243392Skarels int *retval; 6343392Skarels { 6454784Storek struct timeval atv, delta; 658034Sroot struct timezone atz; 6643392Skarels int error, s; 677500Sroot 6847540Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 6944405Skarels return (error); 7054784Storek /* Verify all parameters before changing time. */ 7154784Storek if (uap->tv && 7254784Storek (error = copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof(atv)))) 7354784Storek return (error); 7454784Storek if (uap->tzp && 7554784Storek (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz)))) 7654784Storek return (error); 7730666Sbostic if (uap->tv) { 7837583Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */ 7954784Storek s = splclock(); 8054784Storek /* nb. delta.tv_usec may be < 0, but this is OK here */ 8154784Storek delta.tv_sec = atv.tv_sec - time.tv_sec; 8254784Storek delta.tv_usec = atv.tv_usec - time.tv_usec; 8354784Storek time = atv; 8454784Storek (void) splsoftclock(); 8554784Storek timevaladd(&boottime, &delta); 8654784Storek timevalfix(&boottime); 8754784Storek timevaladd(&runtime, &delta); 8854784Storek timevalfix(&runtime); 89*67639Smckusick # ifdef NFS 90*67639Smckusick lease_updatetime(delta.tv_sec); 91*67639Smckusick # endif 9254784Storek splx(s); 9337583Smckusick resettodr(); 9430666Sbostic } 9554784Storek if (uap->tzp) 9637591Smckusick tz = atz; 9754784Storek return (0); 987500Sroot } 997500Sroot 10028829Skarels extern int tickadj; /* "standard" clock skew, us./tick */ 10128829Skarels int tickdelta; /* current clock skew, us. per tick */ 10228829Skarels long timedelta; /* unapplied time correction, us. */ 10328829Skarels long bigadj = 1000000; /* use 10x skew above bigadj us. */ 10417356Skarels 10554927Storek struct adjtime_args { 10654927Storek struct timeval *delta; 10754927Storek struct timeval *olddelta; 10854927Storek }; 10943392Skarels /* ARGSUSED */ 11043392Skarels adjtime(p, uap, retval) 11143392Skarels struct proc *p; 11254927Storek register struct adjtime_args *uap; 11343392Skarels int *retval; 11443392Skarels { 11555293Storek struct timeval atv; 11655293Storek register long ndelta, ntickdelta, odelta; 11743392Skarels int s, error; 11817356Skarels 11947540Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 12044405Skarels return (error); 12143392Skarels if (error = 12255293Storek copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval))) 12344405Skarels return (error); 12455293Storek 12555293Storek /* 12655293Storek * Compute the total correction and the rate at which to apply it. 12755293Storek * Round the adjustment down to a whole multiple of the per-tick 12855293Storek * delta, so that after some number of incremental changes in 12955293Storek * hardclock(), tickdelta will become zero, lest the correction 13055293Storek * overshoot and start taking us away from the desired final time. 13155293Storek */ 13228829Skarels ndelta = atv.tv_sec * 1000000 + atv.tv_usec; 13355293Storek if (ndelta > bigadj) 13455293Storek ntickdelta = 10 * tickadj; 13555293Storek else 13655293Storek ntickdelta = tickadj; 13755293Storek if (ndelta % ntickdelta) 13855293Storek ndelta = ndelta / ntickdelta * ntickdelta; 13928829Skarels 14055293Storek /* 14155293Storek * To make hardclock()'s job easier, make the per-tick delta negative 14255293Storek * if we want time to run slower; then hardclock can simply compute 14355293Storek * tick + tickdelta, and subtract tickdelta from timedelta. 14455293Storek */ 14555293Storek if (ndelta < 0) 14655293Storek ntickdelta = -ntickdelta; 14725170Skarels s = splclock(); 14855293Storek odelta = timedelta; 14928829Skarels timedelta = ndelta; 15055293Storek tickdelta = ntickdelta; 15128829Skarels splx(s); 15228829Skarels 15355293Storek if (uap->olddelta) { 15455293Storek atv.tv_sec = odelta / 1000000; 15555293Storek atv.tv_usec = odelta % 1000000; 15655293Storek (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta, 15755293Storek sizeof(struct timeval)); 15855293Storek } 15944405Skarels return (0); 16017356Skarels } 16117356Skarels 1628146Sroot /* 1638146Sroot * Get value of an interval timer. The process virtual and 16447540Skarels * profiling virtual time timers are kept in the p_stats area, since 1658146Sroot * they can be swapped out. These are kept internally in the 1668146Sroot * way they are specified externally: in time until they expire. 1678146Sroot * 1688146Sroot * The real time interval timer is kept in the process table slot 1698146Sroot * for the process, and its value (it_value) is kept as an 1708146Sroot * absolute time rather than as a delta, so that it is easy to keep 1718146Sroot * periodic real-time signals from drifting. 1728146Sroot * 1738146Sroot * Virtual time timers are processed in the hardclock() routine of 1748146Sroot * kern_clock.c. The real time timer is processed by a timeout 1758146Sroot * routine, called from the softclock() routine. Since a callout 1768146Sroot * may be delayed in real time due to interrupt processing in the system, 1778146Sroot * it is possible for the real time timeout routine (realitexpire, given below), 1788146Sroot * to be delayed in real time past when it is supposed to occur. It 1798146Sroot * does not suffice, therefore, to reload the real timer .it_value from the 1808146Sroot * real time timers .it_interval. Rather, we compute the next time in 1818146Sroot * absolute time the timer should go off. 1828146Sroot */ 18354927Storek struct getitimer_args { 18454927Storek u_int which; 18554927Storek struct itimerval *itv; 18654927Storek }; 18743392Skarels /* ARGSUSED */ 18843392Skarels getitimer(p, uap, retval) 18943392Skarels struct proc *p; 19054927Storek register struct getitimer_args *uap; 19143392Skarels int *retval; 19243392Skarels { 1938114Sroot struct itimerval aitv; 1948034Sroot int s; 1957424Sroot 19643392Skarels if (uap->which > ITIMER_PROF) 19744405Skarels return (EINVAL); 19825897Skarels s = splclock(); 1998114Sroot if (uap->which == ITIMER_REAL) { 2008146Sroot /* 2018146Sroot * Convert from absoulte to relative time in .it_value 2028146Sroot * part of real time timer. If time for real time timer 2038146Sroot * has passed return 0, else return difference between 2048146Sroot * current time and time for the timer to go off. 2058146Sroot */ 20643392Skarels aitv = p->p_realtimer; 2078114Sroot if (timerisset(&aitv.it_value)) 2088114Sroot if (timercmp(&aitv.it_value, &time, <)) 2098114Sroot timerclear(&aitv.it_value); 2108114Sroot else 21154784Storek timevalsub(&aitv.it_value, 21254784Storek (struct timeval *)&time); 2138114Sroot } else 21447540Skarels aitv = p->p_stats->p_timer[uap->which]; 2158114Sroot splx(s); 21644405Skarels return (copyout((caddr_t)&aitv, (caddr_t)uap->itv, 21743392Skarels sizeof (struct itimerval))); 2187424Sroot } 2197424Sroot 22054927Storek struct setitimer_args { 22154927Storek u_int which; 22254927Storek struct itimerval *itv, *oitv; 22354927Storek }; 22443392Skarels /* ARGSUSED */ 22543392Skarels setitimer(p, uap, retval) 22643392Skarels struct proc *p; 22754927Storek register struct setitimer_args *uap; 22843392Skarels int *retval; 22943392Skarels { 23037591Smckusick struct itimerval aitv; 23137591Smckusick register struct itimerval *itvp; 23243392Skarels int s, error; 2337424Sroot 23443392Skarels if (uap->which > ITIMER_PROF) 23544405Skarels return (EINVAL); 23637591Smckusick itvp = uap->itv; 23743392Skarels if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv, 23837591Smckusick sizeof(struct itimerval)))) 23944405Skarels return (error); 24043392Skarels if ((uap->itv = uap->oitv) && (error = getitimer(p, uap, retval))) 24144405Skarels return (error); 24237591Smckusick if (itvp == 0) 24343392Skarels return (0); 24443392Skarels if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) 24544405Skarels return (EINVAL); 24625897Skarels s = splclock(); 2478114Sroot if (uap->which == ITIMER_REAL) { 2488625Sroot untimeout(realitexpire, (caddr_t)p); 2498114Sroot if (timerisset(&aitv.it_value)) { 25054784Storek timevaladd(&aitv.it_value, (struct timeval *)&time); 2518625Sroot timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value)); 2528114Sroot } 2538114Sroot p->p_realtimer = aitv; 2548114Sroot } else 25547540Skarels p->p_stats->p_timer[uap->which] = aitv; 2568034Sroot splx(s); 25744405Skarels return (0); 2587424Sroot } 2597424Sroot 2608146Sroot /* 2618146Sroot * Real interval timer expired: 2628146Sroot * send process whose timer expired an alarm signal. 2638146Sroot * If time is not set up to reload, then just return. 2648146Sroot * Else compute next time timer should go off which is > current time. 2658146Sroot * This is where delay in processing this timeout causes multiple 2668146Sroot * SIGALRM calls to be compressed into one. 2678146Sroot */ 26854784Storek void 26954784Storek realitexpire(arg) 27054784Storek void *arg; 27154784Storek { 2728114Sroot register struct proc *p; 2738114Sroot int s; 2748114Sroot 27554784Storek p = (struct proc *)arg; 2768114Sroot psignal(p, SIGALRM); 2778114Sroot if (!timerisset(&p->p_realtimer.it_interval)) { 2788114Sroot timerclear(&p->p_realtimer.it_value); 2798114Sroot return; 2808114Sroot } 2818114Sroot for (;;) { 28225897Skarels s = splclock(); 2838114Sroot timevaladd(&p->p_realtimer.it_value, 2848114Sroot &p->p_realtimer.it_interval); 2858114Sroot if (timercmp(&p->p_realtimer.it_value, &time, >)) { 2868625Sroot timeout(realitexpire, (caddr_t)p, 2878625Sroot hzto(&p->p_realtimer.it_value)); 2888114Sroot splx(s); 2898114Sroot return; 2908114Sroot } 2918114Sroot splx(s); 2928114Sroot } 2938114Sroot } 2948114Sroot 2958146Sroot /* 2968146Sroot * Check that a proposed value to load into the .it_value or 2978146Sroot * .it_interval part of an interval timer is acceptable, and 2988146Sroot * fix it to have at least minimal value (i.e. if it is less 2998146Sroot * than the resolution of the clock, round it up.) 3008146Sroot */ 3018103Sroot itimerfix(tv) 3028103Sroot struct timeval *tv; 3037424Sroot { 3048034Sroot 3058114Sroot if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 3068114Sroot tv->tv_usec < 0 || tv->tv_usec >= 1000000) 3078103Sroot return (EINVAL); 30812970Ssam if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 3098103Sroot tv->tv_usec = tick; 3108103Sroot return (0); 3118034Sroot } 3128034Sroot 3138146Sroot /* 3148146Sroot * Decrement an interval timer by a specified number 3158146Sroot * of microseconds, which must be less than a second, 3168146Sroot * i.e. < 1000000. If the timer expires, then reload 3178146Sroot * it. In this case, carry over (usec - old value) to 31854784Storek * reduce the value reloaded into the timer so that 3198146Sroot * the timer does not drift. This routine assumes 3208146Sroot * that it is called in a context where the timers 3218146Sroot * on which it is operating cannot change in value. 3228146Sroot */ 3238034Sroot itimerdecr(itp, usec) 3248034Sroot register struct itimerval *itp; 3258034Sroot int usec; 3268034Sroot { 3278034Sroot 3288103Sroot if (itp->it_value.tv_usec < usec) { 3298103Sroot if (itp->it_value.tv_sec == 0) { 3308146Sroot /* expired, and already in next interval */ 3318103Sroot usec -= itp->it_value.tv_usec; 3328034Sroot goto expire; 3338103Sroot } 3348103Sroot itp->it_value.tv_usec += 1000000; 3358103Sroot itp->it_value.tv_sec--; 3368034Sroot } 3378103Sroot itp->it_value.tv_usec -= usec; 3388103Sroot usec = 0; 3398103Sroot if (timerisset(&itp->it_value)) 3408034Sroot return (1); 3418146Sroot /* expired, exactly at end of interval */ 3428034Sroot expire: 3438103Sroot if (timerisset(&itp->it_interval)) { 3448103Sroot itp->it_value = itp->it_interval; 3458103Sroot itp->it_value.tv_usec -= usec; 3468103Sroot if (itp->it_value.tv_usec < 0) { 3478103Sroot itp->it_value.tv_usec += 1000000; 3488103Sroot itp->it_value.tv_sec--; 3498103Sroot } 3508103Sroot } else 3518146Sroot itp->it_value.tv_usec = 0; /* sec is already 0 */ 3528034Sroot return (0); 3538034Sroot } 3548034Sroot 3558146Sroot /* 3568146Sroot * Add and subtract routines for timevals. 3578146Sroot * N.B.: subtract routine doesn't deal with 3588146Sroot * results which are before the beginning, 3598146Sroot * it just gets very confused in this case. 3608146Sroot * Caveat emptor. 3618146Sroot */ 3628146Sroot timevaladd(t1, t2) 3638146Sroot struct timeval *t1, *t2; 3648146Sroot { 3658146Sroot 3668146Sroot t1->tv_sec += t2->tv_sec; 3678146Sroot t1->tv_usec += t2->tv_usec; 3688146Sroot timevalfix(t1); 3698146Sroot } 3708146Sroot 3718146Sroot timevalsub(t1, t2) 3728146Sroot struct timeval *t1, *t2; 3738146Sroot { 3748146Sroot 3758146Sroot t1->tv_sec -= t2->tv_sec; 3768146Sroot t1->tv_usec -= t2->tv_usec; 3778146Sroot timevalfix(t1); 3788146Sroot } 3798146Sroot 3808146Sroot timevalfix(t1) 3818146Sroot struct timeval *t1; 3828146Sroot { 3838146Sroot 3848146Sroot if (t1->tv_usec < 0) { 3858146Sroot t1->tv_sec--; 3868146Sroot t1->tv_usec += 1000000; 3878146Sroot } 3888146Sroot if (t1->tv_usec >= 1000000) { 3898146Sroot t1->tv_sec++; 3908146Sroot t1->tv_usec -= 1000000; 3918146Sroot } 3928146Sroot } 393