kern_time.c revision 25583
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
3425583Speter * $Id: kern_time.c,v 1.22 1997/03/22 08:03:32 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>
451541Srgrimes#include <sys/vnode.h>
461541Srgrimes
479369Sdgstruct timezone tz;
489369Sdg
498876Srgrimes/*
501541Srgrimes * Time of day and interval timer support.
511541Srgrimes *
521541Srgrimes * These routines provide the kernel entry points to get and set
531541Srgrimes * the time-of-day and per-process interval timers.  Subroutines
541541Srgrimes * here provide support for adding and subtracting timeval structures
551541Srgrimes * and decrementing interval timers, optionally reloading the interval
561541Srgrimes * timers when they expire.
571541Srgrimes */
581541Srgrimes
5913016Sbdestatic void	timevalfix __P((struct timeval *));
6025583Speterstatic int	settime __P((struct timeval *));
6113016Sbde
6225583Speterstatic int
6325583Spetersettime(tv)
6425583Speter	struct timeval *tv;
6525583Speter{
6625583Speter	struct timeval delta;
6725583Speter	struct proc *p;
6825583Speter	int s;
6925583Speter
7025583Speter	/*
7125583Speter	 * Must not set clock backwards in secure mode
7225583Speter	 */
7325583Speter	delta.tv_sec = tv->tv_sec - time.tv_sec;
7425583Speter	delta.tv_usec = tv->tv_usec - time.tv_usec;
7525583Speter	timevalfix(&delta);
7625583Speter	if (delta.tv_sec < 0 && securelevel > 1)
7725583Speter		return (EPERM);
7825583Speter#ifdef notyet
7925583Speter	if (delta.tv_sec < 86400 && securelevel > 0)
8025583Speter		return (EPERM);
8125583Speter#endif
8225583Speter
8325583Speter	s = splclock();
8425583Speter	/*
8525583Speter	 * Recalculate delta directly to minimize clock interrupt
8625583Speter	 * latency.  Fix it after the ipl has been lowered.
8725583Speter	 */
8825583Speter	delta.tv_sec = tv->tv_sec - time.tv_sec;
8925583Speter	delta.tv_usec = tv->tv_usec - time.tv_usec;
9025583Speter	time = *tv;
9125583Speter	/*
9225583Speter	 * XXX should arrange for microtime() to agree with *tv if
9325583Speter	 * it is called now.  As it is, it may add up to about
9425583Speter	 * `tick' unwanted usec.
9525583Speter	 * Another problem is that clock interrupts may occur at
9625583Speter	 * other than multiples of `tick'.  It's not worth fixing
9725583Speter	 * this here, since the problem is also caused by tick
9825583Speter	 * adjustments.
9925583Speter	 */
10025583Speter	(void) splsoftclock();
10125583Speter	timevaladd(&boottime, &delta);
10225583Speter	timevaladd(&runtime, &delta);
10325583Speter	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next)
10425583Speter		if (timerisset(&p->p_realtimer.it_value))
10525583Speter			timevaladd(&p->p_realtimer.it_value, &delta);
10625583Speter#ifdef NFS
10725583Speter	lease_updatetime(delta.tv_sec);
10825583Speter#endif
10925583Speter	splx(s);
11025583Speter	resettodr();
11125583Speter	return (0);
11225583Speter}
11325583Speter
11412221Sbde#ifndef _SYS_SYSPROTO_H_
11525583Speterstruct clock_gettime_args {
11625583Speter	clockid_t clock_id;
11725583Speter	struct	timespec *tp;
11825583Speter};
11925583Speter#endif
12025583Speter/* ARGSUSED */
12125583Speterint
12225583Speterclock_gettime(p, uap, retval)
12325583Speter	struct proc *p;
12425583Speter	struct clock_gettime_args *uap;
12525583Speter	register_t *retval;
12625583Speter{
12725583Speter	clockid_t clock_id;
12825583Speter	struct timeval atv;
12925583Speter	struct timespec ats;
13025583Speter
13125583Speter	clock_id = SCARG(uap, clock_id);
13225583Speter	if (clock_id != CLOCK_REALTIME)
13325583Speter		return (EINVAL);
13425583Speter
13525583Speter	microtime(&atv);
13625583Speter	TIMEVAL_TO_TIMESPEC(&atv, &ats);
13725583Speter
13825583Speter	return copyout(&ats, SCARG(uap, tp), sizeof(ats));
13925583Speter}
14025583Speter
14125583Speter#ifndef _SYS_SYSPROTO_H_
14225583Speterstruct clock_settime_args {
14325583Speter	clockid_t clock_id;
14425583Speter	const struct	timespec *tp;
14525583Speter};
14625583Speter#endif
14725583Speter/* ARGSUSED */
14825583Speterint
14925583Speterclock_settime(p, uap, retval)
15025583Speter	struct proc *p;
15125583Speter	struct clock_settime_args *uap;
15225583Speter	register_t *retval;
15325583Speter{
15425583Speter	clockid_t clock_id;
15525583Speter	struct timeval atv;
15625583Speter	struct timespec ats;
15725583Speter	int error;
15825583Speter
15925583Speter	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
16025583Speter		return (error);
16125583Speter
16225583Speter	clock_id = SCARG(uap, clock_id);
16325583Speter	if (clock_id != CLOCK_REALTIME)
16425583Speter		return (EINVAL);
16525583Speter
16625583Speter	if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
16725583Speter		return (error);
16825583Speter
16925583Speter	TIMESPEC_TO_TIMEVAL(&atv, &ats);
17025583Speter	if ((error = settime(&atv)))
17125583Speter		return (error);
17225583Speter
17325583Speter	return 0;
17425583Speter}
17525583Speter
17625583Speter#ifndef _SYS_SYSPROTO_H_
17725583Speterstruct clock_getres_args {
17825583Speter	clockid_t clock_id;
17925583Speter	struct	timespec *tp;
18025583Speter};
18125583Speter#endif
18225583Speterint
18325583Speterclock_getres(p, uap, retval)
18425583Speter	struct proc *p;
18525583Speter	struct clock_getres_args *uap;
18625583Speter	register_t *retval;
18725583Speter{
18825583Speter	clockid_t clock_id;
18925583Speter	struct timespec ts;
19025583Speter	int error = 0;
19125583Speter
19225583Speter	clock_id = SCARG(uap, clock_id);
19325583Speter	if (clock_id != CLOCK_REALTIME)
19425583Speter		return (EINVAL);
19525583Speter
19625583Speter	if (SCARG(uap, tp)) {
19725583Speter		ts.tv_sec = 0;
19825583Speter		ts.tv_nsec = 1000000000 / hz;
19925583Speter
20025583Speter		error = copyout(&ts, SCARG(uap, tp), sizeof (ts));
20125583Speter	}
20225583Speter
20325583Speter	return error;
20425583Speter}
20525583Speter
20625583Speter#ifndef _SYS_SYSPROTO_H_
20725583Speterstruct nanosleep_args {
20825583Speter	struct	timespec *rqtp;
20925583Speter	struct	timespec *rmtp;
21025583Speter};
21125583Speter#endif
21225583Speter/* ARGSUSED */
21325583Speterint
21425583Speternanosleep(p, uap, retval)
21525583Speter	struct proc *p;
21625583Speter	struct nanosleep_args *uap;
21725583Speter	register_t *retval;
21825583Speter{
21925583Speter	static int nanowait;
22025583Speter	struct timespec rqt;
22125583Speter	struct timespec rmt;
22225583Speter	struct timeval atv, utv;
22325583Speter	int error, s, timo;
22425583Speter
22525583Speter	error = copyin((caddr_t)SCARG(uap, rqtp), (caddr_t)&rqt,
22625583Speter		       sizeof(struct timespec));
22725583Speter	if (error)
22825583Speter		return (error);
22925583Speter
23025583Speter	TIMESPEC_TO_TIMEVAL(&atv, &rqt)
23125583Speter	if (itimerfix(&atv))
23225583Speter		return (EINVAL);
23325583Speter
23425583Speter	s = splclock();
23525583Speter	timevaladd(&atv, &time);
23625583Speter	timo = hzto(&atv);
23725583Speter	/*
23825583Speter	 * Avoid inadvertantly sleeping forever
23925583Speter	 */
24025583Speter	if (timo == 0)
24125583Speter		timo = 1;
24225583Speter	splx(s);
24325583Speter
24425583Speter	error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
24525583Speter	if (error == ERESTART)
24625583Speter		error = EINTR;
24725583Speter	if (error == EWOULDBLOCK)
24825583Speter		error = 0;
24925583Speter
25025583Speter	if (SCARG(uap, rmtp)) {
25125583Speter		int error;
25225583Speter
25325583Speter		s = splclock();
25425583Speter		utv = time;
25525583Speter		splx(s);
25625583Speter
25725583Speter		timevalsub(&atv, &utv);
25825583Speter		if (atv.tv_sec < 0)
25925583Speter			timerclear(&atv);
26025583Speter
26125583Speter		TIMEVAL_TO_TIMESPEC(&atv, &rmt);
26225583Speter		error = copyout((caddr_t)&rmt, (caddr_t)SCARG(uap, rmtp),
26325583Speter			sizeof(rmt));
26425583Speter		if (error)
26525583Speter			return (error);
26625583Speter	}
26725583Speter
26825583Speter	return error;
26925583Speter}
27025583Speter
27125583Speter
27225583Speter#ifndef _SYS_SYSPROTO_H_
2731541Srgrimesstruct gettimeofday_args {
2741541Srgrimes	struct	timeval *tp;
2751541Srgrimes	struct	timezone *tzp;
2761541Srgrimes};
27712221Sbde#endif
2781541Srgrimes/* ARGSUSED */
2791549Srgrimesint
2801541Srgrimesgettimeofday(p, uap, retval)
2811541Srgrimes	struct proc *p;
2821541Srgrimes	register struct gettimeofday_args *uap;
2831541Srgrimes	int *retval;
2841541Srgrimes{
2851541Srgrimes	struct timeval atv;
2861541Srgrimes	int error = 0;
2871541Srgrimes
2881541Srgrimes	if (uap->tp) {
2891541Srgrimes		microtime(&atv);
2903098Sphk		if ((error = copyout((caddr_t)&atv, (caddr_t)uap->tp,
2913098Sphk		    sizeof (atv))))
2921541Srgrimes			return (error);
2931541Srgrimes	}
2941541Srgrimes	if (uap->tzp)
2951541Srgrimes		error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
2961541Srgrimes		    sizeof (tz));
2971541Srgrimes	return (error);
2981541Srgrimes}
2991541Srgrimes
30012221Sbde#ifndef _SYS_SYSPROTO_H_
3011541Srgrimesstruct settimeofday_args {
3021541Srgrimes	struct	timeval *tv;
3031541Srgrimes	struct	timezone *tzp;
3041541Srgrimes};
30512221Sbde#endif
3061541Srgrimes/* ARGSUSED */
3071549Srgrimesint
3081541Srgrimessettimeofday(p, uap, retval)
3091541Srgrimes	struct proc *p;
3101541Srgrimes	struct settimeofday_args *uap;
3111541Srgrimes	int *retval;
3121541Srgrimes{
3131541Srgrimes	struct timeval atv, delta;
3141541Srgrimes	struct timezone atz;
3151541Srgrimes	int error, s;
3161541Srgrimes
3173098Sphk	if ((error = suser(p->p_ucred, &p->p_acflag)))
3181541Srgrimes		return (error);
3191541Srgrimes	/* Verify all parameters before changing time. */
3201541Srgrimes	if (uap->tv &&
3211541Srgrimes	    (error = copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof(atv))))
3221541Srgrimes		return (error);
32312381Sbde	if (atv.tv_usec < 0 || atv.tv_usec >= 1000000)
32412381Sbde		return (EINVAL);
3251541Srgrimes	if (uap->tzp &&
3261541Srgrimes	    (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz))))
3271541Srgrimes		return (error);
32825583Speter	if (uap->tv && (error = settime(&atv)))
32925583Speter		return (error);
3301541Srgrimes	if (uap->tzp)
3311541Srgrimes		tz = atz;
3321541Srgrimes	return (0);
3331541Srgrimes}
3341541Srgrimes
3351541Srgrimesextern	int tickadj;			/* "standard" clock skew, us./tick */
3361541Srgrimesint	tickdelta;			/* current clock skew, us. per tick */
3371541Srgrimeslong	timedelta;			/* unapplied time correction, us. */
33812819Sphkstatic long	bigadj = 1000000;	/* use 10x skew above bigadj us. */
3391541Srgrimes
34012221Sbde#ifndef _SYS_SYSPROTO_H_
3411541Srgrimesstruct adjtime_args {
3421541Srgrimes	struct timeval *delta;
3431541Srgrimes	struct timeval *olddelta;
3441541Srgrimes};
34512221Sbde#endif
3461541Srgrimes/* ARGSUSED */
3471549Srgrimesint
3481541Srgrimesadjtime(p, uap, retval)
3491541Srgrimes	struct proc *p;
3501541Srgrimes	register struct adjtime_args *uap;
3511541Srgrimes	int *retval;
3521541Srgrimes{
3531541Srgrimes	struct timeval atv;
3541541Srgrimes	register long ndelta, ntickdelta, odelta;
3551541Srgrimes	int s, error;
3561541Srgrimes
3573098Sphk	if ((error = suser(p->p_ucred, &p->p_acflag)))
3581541Srgrimes		return (error);
3593098Sphk	if ((error =
3603098Sphk	    copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval))))
3611541Srgrimes		return (error);
3621541Srgrimes
3631541Srgrimes	/*
3641541Srgrimes	 * Compute the total correction and the rate at which to apply it.
3651541Srgrimes	 * Round the adjustment down to a whole multiple of the per-tick
3661541Srgrimes	 * delta, so that after some number of incremental changes in
3671541Srgrimes	 * hardclock(), tickdelta will become zero, lest the correction
3681541Srgrimes	 * overshoot and start taking us away from the desired final time.
3691541Srgrimes	 */
3701541Srgrimes	ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
37117123Sbde	if (ndelta > bigadj || ndelta < -bigadj)
3721541Srgrimes		ntickdelta = 10 * tickadj;
3731541Srgrimes	else
3741541Srgrimes		ntickdelta = tickadj;
3751541Srgrimes	if (ndelta % ntickdelta)
3761541Srgrimes		ndelta = ndelta / ntickdelta * ntickdelta;
3771541Srgrimes
3781541Srgrimes	/*
3791541Srgrimes	 * To make hardclock()'s job easier, make the per-tick delta negative
3801541Srgrimes	 * if we want time to run slower; then hardclock can simply compute
3811541Srgrimes	 * tick + tickdelta, and subtract tickdelta from timedelta.
3821541Srgrimes	 */
3831541Srgrimes	if (ndelta < 0)
3841541Srgrimes		ntickdelta = -ntickdelta;
3851541Srgrimes	s = splclock();
3861541Srgrimes	odelta = timedelta;
3871541Srgrimes	timedelta = ndelta;
3881541Srgrimes	tickdelta = ntickdelta;
3891541Srgrimes	splx(s);
3901541Srgrimes
3911541Srgrimes	if (uap->olddelta) {
3921541Srgrimes		atv.tv_sec = odelta / 1000000;
3931541Srgrimes		atv.tv_usec = odelta % 1000000;
3941541Srgrimes		(void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta,
3951541Srgrimes		    sizeof(struct timeval));
3961541Srgrimes	}
3971541Srgrimes	return (0);
3981541Srgrimes}
3991541Srgrimes
4001541Srgrimes/*
4011541Srgrimes * Get value of an interval timer.  The process virtual and
4021541Srgrimes * profiling virtual time timers are kept in the p_stats area, since
4031541Srgrimes * they can be swapped out.  These are kept internally in the
4041541Srgrimes * way they are specified externally: in time until they expire.
4051541Srgrimes *
4061541Srgrimes * The real time interval timer is kept in the process table slot
4071541Srgrimes * for the process, and its value (it_value) is kept as an
4081541Srgrimes * absolute time rather than as a delta, so that it is easy to keep
4091541Srgrimes * periodic real-time signals from drifting.
4101541Srgrimes *
4111541Srgrimes * Virtual time timers are processed in the hardclock() routine of
4121541Srgrimes * kern_clock.c.  The real time timer is processed by a timeout
4131541Srgrimes * routine, called from the softclock() routine.  Since a callout
4141541Srgrimes * may be delayed in real time due to interrupt processing in the system,
4151541Srgrimes * it is possible for the real time timeout routine (realitexpire, given below),
4161541Srgrimes * to be delayed in real time past when it is supposed to occur.  It
4171541Srgrimes * does not suffice, therefore, to reload the real timer .it_value from the
4181541Srgrimes * real time timers .it_interval.  Rather, we compute the next time in
4191541Srgrimes * absolute time the timer should go off.
4201541Srgrimes */
42112221Sbde#ifndef _SYS_SYSPROTO_H_
4221541Srgrimesstruct getitimer_args {
4231541Srgrimes	u_int	which;
4241541Srgrimes	struct	itimerval *itv;
4251541Srgrimes};
42612221Sbde#endif
4271541Srgrimes/* ARGSUSED */
4281549Srgrimesint
4291541Srgrimesgetitimer(p, uap, retval)
4301541Srgrimes	struct proc *p;
4311541Srgrimes	register struct getitimer_args *uap;
4321541Srgrimes	int *retval;
4331541Srgrimes{
4341541Srgrimes	struct itimerval aitv;
4351541Srgrimes	int s;
4361541Srgrimes
4371541Srgrimes	if (uap->which > ITIMER_PROF)
4381541Srgrimes		return (EINVAL);
4391541Srgrimes	s = splclock();
4401541Srgrimes	if (uap->which == ITIMER_REAL) {
4411541Srgrimes		/*
4421541Srgrimes		 * Convert from absoulte to relative time in .it_value
4431541Srgrimes		 * part of real time timer.  If time for real time timer
4441541Srgrimes		 * has passed return 0, else return difference between
4451541Srgrimes		 * current time and time for the timer to go off.
4461541Srgrimes		 */
4471541Srgrimes		aitv = p->p_realtimer;
4481541Srgrimes		if (timerisset(&aitv.it_value))
4491541Srgrimes			if (timercmp(&aitv.it_value, &time, <))
4501541Srgrimes				timerclear(&aitv.it_value);
4511541Srgrimes			else
45224102Sbde				timevalsub(&aitv.it_value, &time);
4531541Srgrimes	} else
4541541Srgrimes		aitv = p->p_stats->p_timer[uap->which];
4551541Srgrimes	splx(s);
4561541Srgrimes	return (copyout((caddr_t)&aitv, (caddr_t)uap->itv,
4571541Srgrimes	    sizeof (struct itimerval)));
4581541Srgrimes}
4591541Srgrimes
46012221Sbde#ifndef _SYS_SYSPROTO_H_
4611541Srgrimesstruct setitimer_args {
4621541Srgrimes	u_int	which;
4631541Srgrimes	struct	itimerval *itv, *oitv;
4641541Srgrimes};
46512221Sbde#endif
4661541Srgrimes/* ARGSUSED */
4671549Srgrimesint
4681541Srgrimessetitimer(p, uap, retval)
4691541Srgrimes	struct proc *p;
4701541Srgrimes	register struct setitimer_args *uap;
4711541Srgrimes	int *retval;
4721541Srgrimes{
4731541Srgrimes	struct itimerval aitv;
4741541Srgrimes	register struct itimerval *itvp;
4751541Srgrimes	int s, error;
4761541Srgrimes
4771541Srgrimes	if (uap->which > ITIMER_PROF)
4781541Srgrimes		return (EINVAL);
4791541Srgrimes	itvp = uap->itv;
4801541Srgrimes	if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
4811541Srgrimes	    sizeof(struct itimerval))))
4821541Srgrimes		return (error);
48312381Sbde	if ((uap->itv = uap->oitv) &&
48412381Sbde	    (error = getitimer(p, (struct getitimer_args *)uap, retval)))
4851541Srgrimes		return (error);
4861541Srgrimes	if (itvp == 0)
4871541Srgrimes		return (0);
4881541Srgrimes	if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
4891541Srgrimes		return (EINVAL);
4901541Srgrimes	s = splclock();
4911541Srgrimes	if (uap->which == ITIMER_REAL) {
4921541Srgrimes		untimeout(realitexpire, (caddr_t)p);
4931541Srgrimes		if (timerisset(&aitv.it_value)) {
49424102Sbde			timevaladd(&aitv.it_value, &time);
4951541Srgrimes			timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value));
4961541Srgrimes		}
4971541Srgrimes		p->p_realtimer = aitv;
4981541Srgrimes	} else
4991541Srgrimes		p->p_stats->p_timer[uap->which] = aitv;
5001541Srgrimes	splx(s);
5011541Srgrimes	return (0);
5021541Srgrimes}
5031541Srgrimes
5041541Srgrimes/*
5051541Srgrimes * Real interval timer expired:
5061541Srgrimes * send process whose timer expired an alarm signal.
5071541Srgrimes * If time is not set up to reload, then just return.
5081541Srgrimes * Else compute next time timer should go off which is > current time.
5091541Srgrimes * This is where delay in processing this timeout causes multiple
5101541Srgrimes * SIGALRM calls to be compressed into one.
5119327Sbde * hzto() always adds 1 to allow for the time until the next clock
5129327Sbde * interrupt being strictly less than 1 clock tick, but we don't want
5139327Sbde * that here since we want to appear to be in sync with the clock
5149327Sbde * interrupt even when we're delayed.
5151541Srgrimes */
5161541Srgrimesvoid
5171541Srgrimesrealitexpire(arg)
5181541Srgrimes	void *arg;
5191541Srgrimes{
5201541Srgrimes	register struct proc *p;
5211541Srgrimes	int s;
5221541Srgrimes
5231541Srgrimes	p = (struct proc *)arg;
5241541Srgrimes	psignal(p, SIGALRM);
5251541Srgrimes	if (!timerisset(&p->p_realtimer.it_interval)) {
5261541Srgrimes		timerclear(&p->p_realtimer.it_value);
5271541Srgrimes		return;
5281541Srgrimes	}
5291541Srgrimes	for (;;) {
5301541Srgrimes		s = splclock();
5311541Srgrimes		timevaladd(&p->p_realtimer.it_value,
5321541Srgrimes		    &p->p_realtimer.it_interval);
5331541Srgrimes		if (timercmp(&p->p_realtimer.it_value, &time, >)) {
5341541Srgrimes			timeout(realitexpire, (caddr_t)p,
5359327Sbde			    hzto(&p->p_realtimer.it_value) - 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;
5891541Srgrimes	if (timerisset(&itp->it_value))
5901541Srgrimes		return (1);
5911541Srgrimes	/* expired, exactly at end of interval */
5921541Srgrimesexpire:
5931541Srgrimes	if (timerisset(&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