123377Smckusick /* 237583Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337583Smckusick * All rights reserved. 423377Smckusick * 544441Sbostic * %sccs.include.redist.c% 637583Smckusick * 7*56517Sbostic * @(#)kern_time.c 7.20 (Berkeley) 10/11/92 823377Smckusick */ 97424Sroot 10*56517Sbostic #include <sys/param.h> 11*56517Sbostic #include <sys/resourcevar.h> 12*56517Sbostic #include <sys/kernel.h> 13*56517Sbostic #include <sys/systm.h> 14*56517Sbostic #include <sys/proc.h> 15*56517Sbostic #include <sys/vnode.h> 167424Sroot 17*56517Sbostic #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); 8954784Storek LEASE_UPDATETIME(delta.tv_sec); 9054784Storek splx(s); 9137583Smckusick resettodr(); 9230666Sbostic } 9354784Storek if (uap->tzp) 9437591Smckusick tz = atz; 9554784Storek return (0); 967500Sroot } 977500Sroot 9828829Skarels extern int tickadj; /* "standard" clock skew, us./tick */ 9928829Skarels int tickdelta; /* current clock skew, us. per tick */ 10028829Skarels long timedelta; /* unapplied time correction, us. */ 10128829Skarels long bigadj = 1000000; /* use 10x skew above bigadj us. */ 10217356Skarels 10354927Storek struct adjtime_args { 10454927Storek struct timeval *delta; 10554927Storek struct timeval *olddelta; 10654927Storek }; 10743392Skarels /* ARGSUSED */ 10843392Skarels adjtime(p, uap, retval) 10943392Skarels struct proc *p; 11054927Storek register struct adjtime_args *uap; 11143392Skarels int *retval; 11243392Skarels { 11355293Storek struct timeval atv; 11455293Storek register long ndelta, ntickdelta, odelta; 11543392Skarels int s, error; 11617356Skarels 11747540Skarels if (error = suser(p->p_ucred, &p->p_acflag)) 11844405Skarels return (error); 11943392Skarels if (error = 12055293Storek copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval))) 12144405Skarels return (error); 12255293Storek 12355293Storek /* 12455293Storek * Compute the total correction and the rate at which to apply it. 12555293Storek * Round the adjustment down to a whole multiple of the per-tick 12655293Storek * delta, so that after some number of incremental changes in 12755293Storek * hardclock(), tickdelta will become zero, lest the correction 12855293Storek * overshoot and start taking us away from the desired final time. 12955293Storek */ 13028829Skarels ndelta = atv.tv_sec * 1000000 + atv.tv_usec; 13155293Storek if (ndelta > bigadj) 13255293Storek ntickdelta = 10 * tickadj; 13355293Storek else 13455293Storek ntickdelta = tickadj; 13555293Storek if (ndelta % ntickdelta) 13655293Storek ndelta = ndelta / ntickdelta * ntickdelta; 13728829Skarels 13855293Storek /* 13955293Storek * To make hardclock()'s job easier, make the per-tick delta negative 14055293Storek * if we want time to run slower; then hardclock can simply compute 14155293Storek * tick + tickdelta, and subtract tickdelta from timedelta. 14255293Storek */ 14355293Storek if (ndelta < 0) 14455293Storek ntickdelta = -ntickdelta; 14525170Skarels s = splclock(); 14655293Storek odelta = timedelta; 14728829Skarels timedelta = ndelta; 14855293Storek tickdelta = ntickdelta; 14928829Skarels splx(s); 15028829Skarels 15155293Storek if (uap->olddelta) { 15255293Storek atv.tv_sec = odelta / 1000000; 15355293Storek atv.tv_usec = odelta % 1000000; 15455293Storek (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta, 15555293Storek sizeof(struct timeval)); 15655293Storek } 15744405Skarels return (0); 15817356Skarels } 15917356Skarels 1608146Sroot /* 1618146Sroot * Get value of an interval timer. The process virtual and 16247540Skarels * profiling virtual time timers are kept in the p_stats area, since 1638146Sroot * they can be swapped out. These are kept internally in the 1648146Sroot * way they are specified externally: in time until they expire. 1658146Sroot * 1668146Sroot * The real time interval timer is kept in the process table slot 1678146Sroot * for the process, and its value (it_value) is kept as an 1688146Sroot * absolute time rather than as a delta, so that it is easy to keep 1698146Sroot * periodic real-time signals from drifting. 1708146Sroot * 1718146Sroot * Virtual time timers are processed in the hardclock() routine of 1728146Sroot * kern_clock.c. The real time timer is processed by a timeout 1738146Sroot * routine, called from the softclock() routine. Since a callout 1748146Sroot * may be delayed in real time due to interrupt processing in the system, 1758146Sroot * it is possible for the real time timeout routine (realitexpire, given below), 1768146Sroot * to be delayed in real time past when it is supposed to occur. It 1778146Sroot * does not suffice, therefore, to reload the real timer .it_value from the 1788146Sroot * real time timers .it_interval. Rather, we compute the next time in 1798146Sroot * absolute time the timer should go off. 1808146Sroot */ 18154927Storek struct getitimer_args { 18254927Storek u_int which; 18354927Storek struct itimerval *itv; 18454927Storek }; 18543392Skarels /* ARGSUSED */ 18643392Skarels getitimer(p, uap, retval) 18743392Skarels struct proc *p; 18854927Storek register struct getitimer_args *uap; 18943392Skarels int *retval; 19043392Skarels { 1918114Sroot struct itimerval aitv; 1928034Sroot int s; 1937424Sroot 19443392Skarels if (uap->which > ITIMER_PROF) 19544405Skarels return (EINVAL); 19625897Skarels s = splclock(); 1978114Sroot if (uap->which == ITIMER_REAL) { 1988146Sroot /* 1998146Sroot * Convert from absoulte to relative time in .it_value 2008146Sroot * part of real time timer. If time for real time timer 2018146Sroot * has passed return 0, else return difference between 2028146Sroot * current time and time for the timer to go off. 2038146Sroot */ 20443392Skarels aitv = p->p_realtimer; 2058114Sroot if (timerisset(&aitv.it_value)) 2068114Sroot if (timercmp(&aitv.it_value, &time, <)) 2078114Sroot timerclear(&aitv.it_value); 2088114Sroot else 20954784Storek timevalsub(&aitv.it_value, 21054784Storek (struct timeval *)&time); 2118114Sroot } else 21247540Skarels aitv = p->p_stats->p_timer[uap->which]; 2138114Sroot splx(s); 21444405Skarels return (copyout((caddr_t)&aitv, (caddr_t)uap->itv, 21543392Skarels sizeof (struct itimerval))); 2167424Sroot } 2177424Sroot 21854927Storek struct setitimer_args { 21954927Storek u_int which; 22054927Storek struct itimerval *itv, *oitv; 22154927Storek }; 22243392Skarels /* ARGSUSED */ 22343392Skarels setitimer(p, uap, retval) 22443392Skarels struct proc *p; 22554927Storek register struct setitimer_args *uap; 22643392Skarels int *retval; 22743392Skarels { 22837591Smckusick struct itimerval aitv; 22937591Smckusick register struct itimerval *itvp; 23043392Skarels int s, error; 2317424Sroot 23243392Skarels if (uap->which > ITIMER_PROF) 23344405Skarels return (EINVAL); 23437591Smckusick itvp = uap->itv; 23543392Skarels if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv, 23637591Smckusick sizeof(struct itimerval)))) 23744405Skarels return (error); 23843392Skarels if ((uap->itv = uap->oitv) && (error = getitimer(p, uap, retval))) 23944405Skarels return (error); 24037591Smckusick if (itvp == 0) 24143392Skarels return (0); 24243392Skarels if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval)) 24344405Skarels return (EINVAL); 24425897Skarels s = splclock(); 2458114Sroot if (uap->which == ITIMER_REAL) { 2468625Sroot untimeout(realitexpire, (caddr_t)p); 2478114Sroot if (timerisset(&aitv.it_value)) { 24854784Storek timevaladd(&aitv.it_value, (struct timeval *)&time); 2498625Sroot timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value)); 2508114Sroot } 2518114Sroot p->p_realtimer = aitv; 2528114Sroot } else 25347540Skarels p->p_stats->p_timer[uap->which] = aitv; 2548034Sroot splx(s); 25544405Skarels return (0); 2567424Sroot } 2577424Sroot 2588146Sroot /* 2598146Sroot * Real interval timer expired: 2608146Sroot * send process whose timer expired an alarm signal. 2618146Sroot * If time is not set up to reload, then just return. 2628146Sroot * Else compute next time timer should go off which is > current time. 2638146Sroot * This is where delay in processing this timeout causes multiple 2648146Sroot * SIGALRM calls to be compressed into one. 2658146Sroot */ 26654784Storek void 26754784Storek realitexpire(arg) 26854784Storek void *arg; 26954784Storek { 2708114Sroot register struct proc *p; 2718114Sroot int s; 2728114Sroot 27354784Storek p = (struct proc *)arg; 2748114Sroot psignal(p, SIGALRM); 2758114Sroot if (!timerisset(&p->p_realtimer.it_interval)) { 2768114Sroot timerclear(&p->p_realtimer.it_value); 2778114Sroot return; 2788114Sroot } 2798114Sroot for (;;) { 28025897Skarels s = splclock(); 2818114Sroot timevaladd(&p->p_realtimer.it_value, 2828114Sroot &p->p_realtimer.it_interval); 2838114Sroot if (timercmp(&p->p_realtimer.it_value, &time, >)) { 2848625Sroot timeout(realitexpire, (caddr_t)p, 2858625Sroot hzto(&p->p_realtimer.it_value)); 2868114Sroot splx(s); 2878114Sroot return; 2888114Sroot } 2898114Sroot splx(s); 2908114Sroot } 2918114Sroot } 2928114Sroot 2938146Sroot /* 2948146Sroot * Check that a proposed value to load into the .it_value or 2958146Sroot * .it_interval part of an interval timer is acceptable, and 2968146Sroot * fix it to have at least minimal value (i.e. if it is less 2978146Sroot * than the resolution of the clock, round it up.) 2988146Sroot */ 2998103Sroot itimerfix(tv) 3008103Sroot struct timeval *tv; 3017424Sroot { 3028034Sroot 3038114Sroot if (tv->tv_sec < 0 || tv->tv_sec > 100000000 || 3048114Sroot tv->tv_usec < 0 || tv->tv_usec >= 1000000) 3058103Sroot return (EINVAL); 30612970Ssam if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick) 3078103Sroot tv->tv_usec = tick; 3088103Sroot return (0); 3098034Sroot } 3108034Sroot 3118146Sroot /* 3128146Sroot * Decrement an interval timer by a specified number 3138146Sroot * of microseconds, which must be less than a second, 3148146Sroot * i.e. < 1000000. If the timer expires, then reload 3158146Sroot * it. In this case, carry over (usec - old value) to 31654784Storek * reduce the value reloaded into the timer so that 3178146Sroot * the timer does not drift. This routine assumes 3188146Sroot * that it is called in a context where the timers 3198146Sroot * on which it is operating cannot change in value. 3208146Sroot */ 3218034Sroot itimerdecr(itp, usec) 3228034Sroot register struct itimerval *itp; 3238034Sroot int usec; 3248034Sroot { 3258034Sroot 3268103Sroot if (itp->it_value.tv_usec < usec) { 3278103Sroot if (itp->it_value.tv_sec == 0) { 3288146Sroot /* expired, and already in next interval */ 3298103Sroot usec -= itp->it_value.tv_usec; 3308034Sroot goto expire; 3318103Sroot } 3328103Sroot itp->it_value.tv_usec += 1000000; 3338103Sroot itp->it_value.tv_sec--; 3348034Sroot } 3358103Sroot itp->it_value.tv_usec -= usec; 3368103Sroot usec = 0; 3378103Sroot if (timerisset(&itp->it_value)) 3388034Sroot return (1); 3398146Sroot /* expired, exactly at end of interval */ 3408034Sroot expire: 3418103Sroot if (timerisset(&itp->it_interval)) { 3428103Sroot itp->it_value = itp->it_interval; 3438103Sroot itp->it_value.tv_usec -= usec; 3448103Sroot if (itp->it_value.tv_usec < 0) { 3458103Sroot itp->it_value.tv_usec += 1000000; 3468103Sroot itp->it_value.tv_sec--; 3478103Sroot } 3488103Sroot } else 3498146Sroot itp->it_value.tv_usec = 0; /* sec is already 0 */ 3508034Sroot return (0); 3518034Sroot } 3528034Sroot 3538146Sroot /* 3548146Sroot * Add and subtract routines for timevals. 3558146Sroot * N.B.: subtract routine doesn't deal with 3568146Sroot * results which are before the beginning, 3578146Sroot * it just gets very confused in this case. 3588146Sroot * Caveat emptor. 3598146Sroot */ 3608146Sroot timevaladd(t1, t2) 3618146Sroot struct timeval *t1, *t2; 3628146Sroot { 3638146Sroot 3648146Sroot t1->tv_sec += t2->tv_sec; 3658146Sroot t1->tv_usec += t2->tv_usec; 3668146Sroot timevalfix(t1); 3678146Sroot } 3688146Sroot 3698146Sroot timevalsub(t1, t2) 3708146Sroot struct timeval *t1, *t2; 3718146Sroot { 3728146Sroot 3738146Sroot t1->tv_sec -= t2->tv_sec; 3748146Sroot t1->tv_usec -= t2->tv_usec; 3758146Sroot timevalfix(t1); 3768146Sroot } 3778146Sroot 3788146Sroot timevalfix(t1) 3798146Sroot struct timeval *t1; 3808146Sroot { 3818146Sroot 3828146Sroot if (t1->tv_usec < 0) { 3838146Sroot t1->tv_sec--; 3848146Sroot t1->tv_usec += 1000000; 3858146Sroot } 3868146Sroot if (t1->tv_usec >= 1000000) { 3878146Sroot t1->tv_sec++; 3888146Sroot t1->tv_usec -= 1000000; 3898146Sroot } 3908146Sroot } 391