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