kern_time.c revision 36128
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
3436128Sbde * $Id: kern_time.c,v 1.56 1998/05/17 20:08:04 bde Exp $
351541Srgrimes */
361541Srgrimes
371541Srgrimes#include <sys/param.h>
3812221Sbde#include <sys/sysproto.h>
391541Srgrimes#include <sys/resourcevar.h>
403308Sphk#include <sys/signalvar.h>
411541Srgrimes#include <sys/kernel.h>
421541Srgrimes#include <sys/systm.h>
4325583Speter#include <sys/sysent.h>
441541Srgrimes#include <sys/proc.h>
4525656Speter#include <sys/time.h>
461541Srgrimes#include <sys/vnode.h>
4726335Speter#include <vm/vm.h>
4826335Speter#include <vm/vm_extern.h>
491541Srgrimes
509369Sdgstruct timezone tz;
519369Sdg
528876Srgrimes/*
531541Srgrimes * Time of day and interval timer support.
541541Srgrimes *
551541Srgrimes * These routines provide the kernel entry points to get and set
561541Srgrimes * the time-of-day and per-process interval timers.  Subroutines
571541Srgrimes * here provide support for adding and subtracting timeval structures
581541Srgrimes * and decrementing interval timers, optionally reloading the interval
591541Srgrimes * timers when they expire.
601541Srgrimes */
611541Srgrimes
6228773Sbdestatic int	nanosleep1 __P((struct proc *p, struct timespec *rqt,
6328773Sbde		    struct timespec *rmt));
6425656Speterstatic int	settime __P((struct timeval *));
6513016Sbdestatic void	timevalfix __P((struct timeval *));
6630994Sphkstatic void	no_lease_updatetime __P((int));
6713016Sbde
6830739Sphkstatic void
6930739Sphkno_lease_updatetime(deltat)
7030739Sphk	int deltat;
7130739Sphk{
7230739Sphk}
7330739Sphk
7430739Sphkvoid (*lease_updatetime) __P((int))  = no_lease_updatetime;
7530739Sphk
7625583Speterstatic int
7725583Spetersettime(tv)
7825583Speter	struct timeval *tv;
7925583Speter{
8033818Sbde	struct timeval delta, tv1;
8133690Sphk	struct timespec ts;
8225583Speter	struct proc *p;
8325583Speter	int s;
8425583Speter
8525656Speter	s = splclock();
8633818Sbde	microtime(&tv1);
8735029Sphk	delta = *tv;
8835029Sphk	timevalsub(&delta, &tv1);
8925583Speter
9025583Speter	/*
9133818Sbde	 * If the system is secure, we do not allow the time to be
9233818Sbde	 * set to an earlier value (it may be slowed using adjtime,
9333818Sbde	 * but not set back). This feature prevent interlopers from
9433818Sbde	 * setting arbitrary time stamps on files.
9525583Speter	 */
9633818Sbde	if (delta.tv_sec < 0 && securelevel > 1) {
9733818Sbde		splx(s);
9833818Sbde		return (EPERM);
9933818Sbde	}
10033818Sbde
10133690Sphk	ts.tv_sec = tv->tv_sec;
10233690Sphk	ts.tv_nsec = tv->tv_usec * 1000;
10333690Sphk	set_timecounter(&ts);
10425583Speter	(void) splsoftclock();
10525583Speter	lease_updatetime(delta.tv_sec);
10625583Speter	splx(s);
10725583Speter	resettodr();
10825583Speter	return (0);
10925583Speter}
11025583Speter
11112221Sbde#ifndef _SYS_SYSPROTO_H_
11225583Speterstruct clock_gettime_args {
11325583Speter	clockid_t clock_id;
11425583Speter	struct	timespec *tp;
11525583Speter};
11625583Speter#endif
11725656Speter
11825583Speter/* ARGSUSED */
11925583Speterint
12030994Sphkclock_gettime(p, uap)
12125583Speter	struct proc *p;
12225583Speter	struct clock_gettime_args *uap;
12325583Speter{
12425583Speter	struct timespec ats;
12525583Speter
12625656Speter	if (SCARG(uap, clock_id) != CLOCK_REALTIME)
12725583Speter		return (EINVAL);
12833690Sphk	nanotime(&ats);
12925656Speter	return (copyout(&ats, SCARG(uap, tp), sizeof(ats)));
13025583Speter}
13125583Speter
13225583Speter#ifndef _SYS_SYSPROTO_H_
13325583Speterstruct clock_settime_args {
13425583Speter	clockid_t clock_id;
13525583Speter	const struct	timespec *tp;
13625583Speter};
13725583Speter#endif
13825656Speter
13925583Speter/* ARGSUSED */
14025583Speterint
14130994Sphkclock_settime(p, uap)
14225583Speter	struct proc *p;
14325583Speter	struct clock_settime_args *uap;
14425583Speter{
14525583Speter	struct timeval atv;
14625583Speter	struct timespec ats;
14725583Speter	int error;
14825583Speter
14925583Speter	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
15025583Speter		return (error);
15125656Speter	if (SCARG(uap, clock_id) != CLOCK_REALTIME)
15225583Speter		return (EINVAL);
15325583Speter	if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
15425583Speter		return (error);
15527855Sbde	if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000)
15625656Speter		return (EINVAL);
15734901Sphk	/* XXX Don't convert nsec->usec and back */
15825583Speter	TIMESPEC_TO_TIMEVAL(&atv, &ats);
15925583Speter	if ((error = settime(&atv)))
16025583Speter		return (error);
16125656Speter	return (0);
16225583Speter}
16325583Speter
16425583Speter#ifndef _SYS_SYSPROTO_H_
16525583Speterstruct clock_getres_args {
16625583Speter	clockid_t clock_id;
16725583Speter	struct	timespec *tp;
16825583Speter};
16925583Speter#endif
17025656Speter
17125583Speterint
17230994Sphkclock_getres(p, uap)
17325583Speter	struct proc *p;
17425583Speter	struct clock_getres_args *uap;
17525583Speter{
17625583Speter	struct timespec ts;
17725656Speter	int error;
17825583Speter
17925656Speter	if (SCARG(uap, clock_id) != CLOCK_REALTIME)
18025583Speter		return (EINVAL);
18125656Speter	error = 0;
18225583Speter	if (SCARG(uap, tp)) {
18325583Speter		ts.tv_sec = 0;
18433690Sphk		ts.tv_nsec = 1000000000 / timecounter->frequency;
18525656Speter		error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
18625583Speter	}
18725656Speter	return (error);
18825583Speter}
18925583Speter
19026335Speterstatic int nanowait;
19125656Speter
19226335Speterstatic int
19326335Speternanosleep1(p, rqt, rmt)
19425583Speter	struct proc *p;
19526335Speter	struct timespec *rqt, *rmt;
19625583Speter{
19735045Sphk	struct timespec ts, ts2, ts3;
19835042Sphk	struct timeval tv;
19935042Sphk	int error;
20025583Speter
20128773Sbde	if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
20225656Speter		return (EINVAL);
20328773Sbde	if (rqt->tv_sec < 0 || rqt->tv_sec == 0 && rqt->tv_nsec == 0)
20428773Sbde		return (0);
20536119Sphk	getnanouptime(&ts);
20635029Sphk	timespecadd(&ts, rqt);
20735042Sphk	TIMESPEC_TO_TIMEVAL(&tv, rqt);
20835042Sphk	for (;;) {
20935042Sphk		error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp",
21035042Sphk		    tvtohz(&tv));
21136119Sphk		getnanouptime(&ts2);
21235042Sphk		if (error != EWOULDBLOCK) {
21335042Sphk			if (error == ERESTART)
21435042Sphk				error = EINTR;
21535042Sphk			if (rmt != NULL) {
21635042Sphk				timespecsub(&ts, &ts2);
21735042Sphk				if (ts.tv_sec < 0)
21835042Sphk					timespecclear(&ts);
21935042Sphk				*rmt = ts;
22035042Sphk			}
22135042Sphk			return (error);
22235042Sphk		}
22335029Sphk		if (timespeccmp(&ts2, &ts, >=))
22435042Sphk			return (0);
22535045Sphk		ts3 = ts;
22635045Sphk		timespecsub(&ts3, &ts2);
22735045Sphk		TIMESPEC_TO_TIMEVAL(&tv, &ts3);
22826335Speter	}
22926335Speter}
23025583Speter
23126335Speter#ifndef _SYS_SYSPROTO_H_
23226335Speterstruct nanosleep_args {
23326335Speter	struct	timespec *rqtp;
23426335Speter	struct	timespec *rmtp;
23526335Speter};
23626335Speter#endif
23726335Speter
23826335Speter/* ARGSUSED */
23926335Speterint
24030994Sphknanosleep(p, uap)
24126335Speter	struct proc *p;
24226335Speter	struct nanosleep_args *uap;
24326335Speter{
24426335Speter	struct timespec rmt, rqt;
24526335Speter	int error, error2;
24626335Speter
24726335Speter	error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt));
24826335Speter	if (error)
24926335Speter		return (error);
25026336Speter	if (SCARG(uap, rmtp))
25126336Speter		if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE))
25226336Speter			return (EFAULT);
25326335Speter	error = nanosleep1(p, &rqt, &rmt);
25435043Speter	if (error && SCARG(uap, rmtp)) {
25525656Speter		error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
25626335Speter		if (error2)	/* XXX shouldn't happen, did useracc() above */
25725656Speter			return (error2);
25825583Speter	}
25925656Speter	return (error);
26025583Speter}
26125583Speter
26226335Speter#ifndef _SYS_SYSPROTO_H_
2631541Srgrimesstruct gettimeofday_args {
2641541Srgrimes	struct	timeval *tp;
2651541Srgrimes	struct	timezone *tzp;
2661541Srgrimes};
26712221Sbde#endif
2681541Srgrimes/* ARGSUSED */
2691549Srgrimesint
27030994Sphkgettimeofday(p, uap)
2711541Srgrimes	struct proc *p;
2721541Srgrimes	register struct gettimeofday_args *uap;
2731541Srgrimes{
2741541Srgrimes	struct timeval atv;
2751541Srgrimes	int error = 0;
2761541Srgrimes
2771541Srgrimes	if (uap->tp) {
2781541Srgrimes		microtime(&atv);
2793098Sphk		if ((error = copyout((caddr_t)&atv, (caddr_t)uap->tp,
2803098Sphk		    sizeof (atv))))
2811541Srgrimes			return (error);
2821541Srgrimes	}
2831541Srgrimes	if (uap->tzp)
2841541Srgrimes		error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
2851541Srgrimes		    sizeof (tz));
2861541Srgrimes	return (error);
2871541Srgrimes}
2881541Srgrimes
28912221Sbde#ifndef _SYS_SYSPROTO_H_
2901541Srgrimesstruct settimeofday_args {
2911541Srgrimes	struct	timeval *tv;
2921541Srgrimes	struct	timezone *tzp;
2931541Srgrimes};
29412221Sbde#endif
2951541Srgrimes/* ARGSUSED */
2961549Srgrimesint
29730994Sphksettimeofday(p, uap)
2981541Srgrimes	struct proc *p;
2991541Srgrimes	struct settimeofday_args *uap;
3001541Srgrimes{
30125656Speter	struct timeval atv;
3021541Srgrimes	struct timezone atz;
30325656Speter	int error;
3041541Srgrimes
3053098Sphk	if ((error = suser(p->p_ucred, &p->p_acflag)))
3061541Srgrimes		return (error);
3071541Srgrimes	/* Verify all parameters before changing time. */
30825656Speter	if (uap->tv) {
30925656Speter		if ((error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
31025656Speter		    sizeof(atv))))
31125656Speter			return (error);
31225656Speter		if (atv.tv_usec < 0 || atv.tv_usec >= 1000000)
31325656Speter			return (EINVAL);
31425656Speter	}
3151541Srgrimes	if (uap->tzp &&
3161541Srgrimes	    (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz))))
3171541Srgrimes		return (error);
31825583Speter	if (uap->tv && (error = settime(&atv)))
31925583Speter		return (error);
3201541Srgrimes	if (uap->tzp)
3211541Srgrimes		tz = atz;
3221541Srgrimes	return (0);
3231541Srgrimes}
3241541Srgrimes
3251541Srgrimesint	tickdelta;			/* current clock skew, us. per tick */
3261541Srgrimeslong	timedelta;			/* unapplied time correction, us. */
32712819Sphkstatic long	bigadj = 1000000;	/* use 10x skew above bigadj us. */
3281541Srgrimes
32912221Sbde#ifndef _SYS_SYSPROTO_H_
3301541Srgrimesstruct adjtime_args {
3311541Srgrimes	struct timeval *delta;
3321541Srgrimes	struct timeval *olddelta;
3331541Srgrimes};
33412221Sbde#endif
3351541Srgrimes/* ARGSUSED */
3361549Srgrimesint
33730994Sphkadjtime(p, uap)
3381541Srgrimes	struct proc *p;
3391541Srgrimes	register struct adjtime_args *uap;
3401541Srgrimes{
3411541Srgrimes	struct timeval atv;
3421541Srgrimes	register long ndelta, ntickdelta, odelta;
3431541Srgrimes	int s, error;
3441541Srgrimes
3453098Sphk	if ((error = suser(p->p_ucred, &p->p_acflag)))
3461541Srgrimes		return (error);
3473098Sphk	if ((error =
3483098Sphk	    copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval))))
3491541Srgrimes		return (error);
3501541Srgrimes
3511541Srgrimes	/*
3521541Srgrimes	 * Compute the total correction and the rate at which to apply it.
3531541Srgrimes	 * Round the adjustment down to a whole multiple of the per-tick
3541541Srgrimes	 * delta, so that after some number of incremental changes in
3551541Srgrimes	 * hardclock(), tickdelta will become zero, lest the correction
3561541Srgrimes	 * overshoot and start taking us away from the desired final time.
3571541Srgrimes	 */
3581541Srgrimes	ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
35917123Sbde	if (ndelta > bigadj || ndelta < -bigadj)
3601541Srgrimes		ntickdelta = 10 * tickadj;
3611541Srgrimes	else
3621541Srgrimes		ntickdelta = tickadj;
3631541Srgrimes	if (ndelta % ntickdelta)
3641541Srgrimes		ndelta = ndelta / ntickdelta * ntickdelta;
3651541Srgrimes
3661541Srgrimes	/*
3671541Srgrimes	 * To make hardclock()'s job easier, make the per-tick delta negative
3681541Srgrimes	 * if we want time to run slower; then hardclock can simply compute
3691541Srgrimes	 * tick + tickdelta, and subtract tickdelta from timedelta.
3701541Srgrimes	 */
3711541Srgrimes	if (ndelta < 0)
3721541Srgrimes		ntickdelta = -ntickdelta;
3731541Srgrimes	s = splclock();
3741541Srgrimes	odelta = timedelta;
3751541Srgrimes	timedelta = ndelta;
3761541Srgrimes	tickdelta = ntickdelta;
3771541Srgrimes	splx(s);
3781541Srgrimes
3791541Srgrimes	if (uap->olddelta) {
3801541Srgrimes		atv.tv_sec = odelta / 1000000;
3811541Srgrimes		atv.tv_usec = odelta % 1000000;
3821541Srgrimes		(void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta,
3831541Srgrimes		    sizeof(struct timeval));
3841541Srgrimes	}
3851541Srgrimes	return (0);
3861541Srgrimes}
3871541Srgrimes
3881541Srgrimes/*
3891541Srgrimes * Get value of an interval timer.  The process virtual and
3901541Srgrimes * profiling virtual time timers are kept in the p_stats area, since
3911541Srgrimes * they can be swapped out.  These are kept internally in the
3921541Srgrimes * way they are specified externally: in time until they expire.
3931541Srgrimes *
3941541Srgrimes * The real time interval timer is kept in the process table slot
3951541Srgrimes * for the process, and its value (it_value) is kept as an
3961541Srgrimes * absolute time rather than as a delta, so that it is easy to keep
3971541Srgrimes * periodic real-time signals from drifting.
3981541Srgrimes *
3991541Srgrimes * Virtual time timers are processed in the hardclock() routine of
4001541Srgrimes * kern_clock.c.  The real time timer is processed by a timeout
4011541Srgrimes * routine, called from the softclock() routine.  Since a callout
4021541Srgrimes * may be delayed in real time due to interrupt processing in the system,
4031541Srgrimes * it is possible for the real time timeout routine (realitexpire, given below),
4041541Srgrimes * to be delayed in real time past when it is supposed to occur.  It
4051541Srgrimes * does not suffice, therefore, to reload the real timer .it_value from the
4061541Srgrimes * real time timers .it_interval.  Rather, we compute the next time in
4071541Srgrimes * absolute time the timer should go off.
4081541Srgrimes */
40912221Sbde#ifndef _SYS_SYSPROTO_H_
4101541Srgrimesstruct getitimer_args {
4111541Srgrimes	u_int	which;
4121541Srgrimes	struct	itimerval *itv;
4131541Srgrimes};
41412221Sbde#endif
4151541Srgrimes/* ARGSUSED */
4161549Srgrimesint
41730994Sphkgetitimer(p, uap)
4181541Srgrimes	struct proc *p;
4191541Srgrimes	register struct getitimer_args *uap;
4201541Srgrimes{
42134961Sphk	struct timeval ctv;
4221541Srgrimes	struct itimerval aitv;
4231541Srgrimes	int s;
4241541Srgrimes
4251541Srgrimes	if (uap->which > ITIMER_PROF)
4261541Srgrimes		return (EINVAL);
42734961Sphk	s = splclock(); /* XXX still needed ? */
4281541Srgrimes	if (uap->which == ITIMER_REAL) {
4291541Srgrimes		/*
43036128Sbde		 * Convert from absolute to relative time in .it_value
4311541Srgrimes		 * part of real time timer.  If time for real time timer
4321541Srgrimes		 * has passed return 0, else return difference between
4331541Srgrimes		 * current time and time for the timer to go off.
4341541Srgrimes		 */
4351541Srgrimes		aitv = p->p_realtimer;
43635058Sphk		if (timevalisset(&aitv.it_value)) {
43736119Sphk			getmicrouptime(&ctv);
43835058Sphk			if (timevalcmp(&aitv.it_value, &ctv, <))
43935058Sphk				timevalclear(&aitv.it_value);
4401541Srgrimes			else
44134961Sphk				timevalsub(&aitv.it_value, &ctv);
44234961Sphk		}
4431541Srgrimes	} else
4441541Srgrimes		aitv = p->p_stats->p_timer[uap->which];
4451541Srgrimes	splx(s);
4461541Srgrimes	return (copyout((caddr_t)&aitv, (caddr_t)uap->itv,
4471541Srgrimes	    sizeof (struct itimerval)));
4481541Srgrimes}
4491541Srgrimes
45012221Sbde#ifndef _SYS_SYSPROTO_H_
4511541Srgrimesstruct setitimer_args {
4521541Srgrimes	u_int	which;
4531541Srgrimes	struct	itimerval *itv, *oitv;
4541541Srgrimes};
45512221Sbde#endif
4561541Srgrimes/* ARGSUSED */
4571549Srgrimesint
45830994Sphksetitimer(p, uap)
4591541Srgrimes	struct proc *p;
4601541Srgrimes	register struct setitimer_args *uap;
4611541Srgrimes{
4621541Srgrimes	struct itimerval aitv;
46334961Sphk	struct timeval ctv;
4641541Srgrimes	register struct itimerval *itvp;
4651541Srgrimes	int s, error;
4661541Srgrimes
4671541Srgrimes	if (uap->which > ITIMER_PROF)
4681541Srgrimes		return (EINVAL);
4691541Srgrimes	itvp = uap->itv;
4701541Srgrimes	if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
4711541Srgrimes	    sizeof(struct itimerval))))
4721541Srgrimes		return (error);
47312381Sbde	if ((uap->itv = uap->oitv) &&
47430994Sphk	    (error = getitimer(p, (struct getitimer_args *)uap)))
4751541Srgrimes		return (error);
4761541Srgrimes	if (itvp == 0)
4771541Srgrimes		return (0);
47828213Sache	if (itimerfix(&aitv.it_value))
4791541Srgrimes		return (EINVAL);
48035058Sphk	if (!timevalisset(&aitv.it_value))
48135058Sphk		timevalclear(&aitv.it_interval);
48228213Sache	else if (itimerfix(&aitv.it_interval))
48328213Sache		return (EINVAL);
48434961Sphk	s = splclock(); /* XXX: still needed ? */
4851541Srgrimes	if (uap->which == ITIMER_REAL) {
48635058Sphk		if (timevalisset(&p->p_realtimer.it_value))
48729680Sgibbs			untimeout(realitexpire, (caddr_t)p, p->p_ithandle);
48835058Sphk		if (timevalisset(&aitv.it_value))
48929680Sgibbs			p->p_ithandle = timeout(realitexpire, (caddr_t)p,
49035033Sphk						tvtohz(&aitv.it_value));
49136119Sphk		getmicrouptime(&ctv);
49235044Sphk		timevaladd(&aitv.it_value, &ctv);
4931541Srgrimes		p->p_realtimer = aitv;
4941541Srgrimes	} else
4951541Srgrimes		p->p_stats->p_timer[uap->which] = aitv;
4961541Srgrimes	splx(s);
4971541Srgrimes	return (0);
4981541Srgrimes}
4991541Srgrimes
5001541Srgrimes/*
5011541Srgrimes * Real interval timer expired:
5021541Srgrimes * send process whose timer expired an alarm signal.
5031541Srgrimes * If time is not set up to reload, then just return.
5041541Srgrimes * Else compute next time timer should go off which is > current time.
5051541Srgrimes * This is where delay in processing this timeout causes multiple
5061541Srgrimes * SIGALRM calls to be compressed into one.
50736127Sbde * tvtohz() always adds 1 to allow for the time until the next clock
5089327Sbde * interrupt being strictly less than 1 clock tick, but we don't want
5099327Sbde * that here since we want to appear to be in sync with the clock
5109327Sbde * interrupt even when we're delayed.
5111541Srgrimes */
5121541Srgrimesvoid
5131541Srgrimesrealitexpire(arg)
5141541Srgrimes	void *arg;
5151541Srgrimes{
5161541Srgrimes	register struct proc *p;
51735044Sphk	struct timeval ctv, ntv;
5181541Srgrimes	int s;
5191541Srgrimes
5201541Srgrimes	p = (struct proc *)arg;
5211541Srgrimes	psignal(p, SIGALRM);
52235058Sphk	if (!timevalisset(&p->p_realtimer.it_interval)) {
52335058Sphk		timevalclear(&p->p_realtimer.it_value);
5241541Srgrimes		return;
5251541Srgrimes	}
5261541Srgrimes	for (;;) {
52734961Sphk		s = splclock(); /* XXX: still neeeded ? */
5281541Srgrimes		timevaladd(&p->p_realtimer.it_value,
5291541Srgrimes		    &p->p_realtimer.it_interval);
53036119Sphk		getmicrouptime(&ctv);
53135058Sphk		if (timevalcmp(&p->p_realtimer.it_value, &ctv, >)) {
53235044Sphk			ntv = p->p_realtimer.it_value;
53335044Sphk			timevalsub(&ntv, &ctv);
53436128Sbde			p->p_ithandle = timeout(realitexpire, (caddr_t)p,
53536128Sbde			    tvtohz(&ntv) - 1);
5361541Srgrimes			splx(s);
5371541Srgrimes			return;
5381541Srgrimes		}
5391541Srgrimes		splx(s);
5401541Srgrimes	}
5411541Srgrimes}
5421541Srgrimes
5431541Srgrimes/*
5441541Srgrimes * Check that a proposed value to load into the .it_value or
5451541Srgrimes * .it_interval part of an interval timer is acceptable, and
5461541Srgrimes * fix it to have at least minimal value (i.e. if it is less
5471541Srgrimes * than the resolution of the clock, round it up.)
5481541Srgrimes */
5491549Srgrimesint
5501541Srgrimesitimerfix(tv)
5511541Srgrimes	struct timeval *tv;
5521541Srgrimes{
5531541Srgrimes
5541541Srgrimes	if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
5551541Srgrimes	    tv->tv_usec < 0 || tv->tv_usec >= 1000000)
5561541Srgrimes		return (EINVAL);
5571541Srgrimes	if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
5581541Srgrimes		tv->tv_usec = tick;
5591541Srgrimes	return (0);
5601541Srgrimes}
5611541Srgrimes
5621541Srgrimes/*
5631541Srgrimes * Decrement an interval timer by a specified number
5641541Srgrimes * of microseconds, which must be less than a second,
5651541Srgrimes * i.e. < 1000000.  If the timer expires, then reload
5661541Srgrimes * it.  In this case, carry over (usec - old value) to
5671541Srgrimes * reduce the value reloaded into the timer so that
5681541Srgrimes * the timer does not drift.  This routine assumes
5691541Srgrimes * that it is called in a context where the timers
5701541Srgrimes * on which it is operating cannot change in value.
5711541Srgrimes */
5721549Srgrimesint
5731541Srgrimesitimerdecr(itp, usec)
5741541Srgrimes	register struct itimerval *itp;
5751541Srgrimes	int usec;
5761541Srgrimes{
5771541Srgrimes
5781541Srgrimes	if (itp->it_value.tv_usec < usec) {
5791541Srgrimes		if (itp->it_value.tv_sec == 0) {
5801541Srgrimes			/* expired, and already in next interval */
5811541Srgrimes			usec -= itp->it_value.tv_usec;
5821541Srgrimes			goto expire;
5831541Srgrimes		}
5841541Srgrimes		itp->it_value.tv_usec += 1000000;
5851541Srgrimes		itp->it_value.tv_sec--;
5861541Srgrimes	}
5871541Srgrimes	itp->it_value.tv_usec -= usec;
5881541Srgrimes	usec = 0;
58935058Sphk	if (timevalisset(&itp->it_value))
5901541Srgrimes		return (1);
5911541Srgrimes	/* expired, exactly at end of interval */
5921541Srgrimesexpire:
59335058Sphk	if (timevalisset(&itp->it_interval)) {
5941541Srgrimes		itp->it_value = itp->it_interval;
5951541Srgrimes		itp->it_value.tv_usec -= usec;
5961541Srgrimes		if (itp->it_value.tv_usec < 0) {
5971541Srgrimes			itp->it_value.tv_usec += 1000000;
5981541Srgrimes			itp->it_value.tv_sec--;
5991541Srgrimes		}
6001541Srgrimes	} else
6011541Srgrimes		itp->it_value.tv_usec = 0;		/* sec is already 0 */
6021541Srgrimes	return (0);
6031541Srgrimes}
6041541Srgrimes
6051541Srgrimes/*
6061541Srgrimes * Add and subtract routines for timevals.
6071541Srgrimes * N.B.: subtract routine doesn't deal with
6081541Srgrimes * results which are before the beginning,
6091541Srgrimes * it just gets very confused in this case.
6101541Srgrimes * Caveat emptor.
6111541Srgrimes */
6121549Srgrimesvoid
6131541Srgrimestimevaladd(t1, t2)
6141541Srgrimes	struct timeval *t1, *t2;
6151541Srgrimes{
6161541Srgrimes
6171541Srgrimes	t1->tv_sec += t2->tv_sec;
6181541Srgrimes	t1->tv_usec += t2->tv_usec;
6191541Srgrimes	timevalfix(t1);
6201541Srgrimes}
6211541Srgrimes
6221549Srgrimesvoid
6231541Srgrimestimevalsub(t1, t2)
6241541Srgrimes	struct timeval *t1, *t2;
6251541Srgrimes{
6261541Srgrimes
6271541Srgrimes	t1->tv_sec -= t2->tv_sec;
6281541Srgrimes	t1->tv_usec -= t2->tv_usec;
6291541Srgrimes	timevalfix(t1);
6301541Srgrimes}
6311541Srgrimes
63212819Sphkstatic void
6331541Srgrimestimevalfix(t1)
6341541Srgrimes	struct timeval *t1;
6351541Srgrimes{
6361541Srgrimes
6371541Srgrimes	if (t1->tv_usec < 0) {
6381541Srgrimes		t1->tv_sec--;
6391541Srgrimes		t1->tv_usec += 1000000;
6401541Srgrimes	}
6411541Srgrimes	if (t1->tv_usec >= 1000000) {
6421541Srgrimes		t1->tv_sec++;
6431541Srgrimes		t1->tv_usec -= 1000000;
6441541Srgrimes	}
6451541Srgrimes}
646