kern_time.c revision 34961
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
3434961Sphk * $Id: kern_time.c,v 1.43 1998/03/26 20:51:41 phk 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);
8733818Sbde	delta.tv_sec = tv->tv_sec - tv1.tv_sec;
8833818Sbde	delta.tv_usec = tv->tv_usec - tv1.tv_usec;
8925583Speter	timevalfix(&delta);
9025583Speter
9125583Speter	/*
9233818Sbde	 * If the system is secure, we do not allow the time to be
9333818Sbde	 * set to an earlier value (it may be slowed using adjtime,
9433818Sbde	 * but not set back). This feature prevent interlopers from
9533818Sbde	 * setting arbitrary time stamps on files.
9625583Speter	 */
9733818Sbde	if (delta.tv_sec < 0 && securelevel > 1) {
9833818Sbde		splx(s);
9933818Sbde		return (EPERM);
10033818Sbde	}
10133818Sbde
10233690Sphk	ts.tv_sec = tv->tv_sec;
10333690Sphk	ts.tv_nsec = tv->tv_usec * 1000;
10433690Sphk	set_timecounter(&ts);
10525583Speter	(void) splsoftclock();
10625583Speter	timevaladd(&boottime, &delta);
10725583Speter	timevaladd(&runtime, &delta);
10826335Speter	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
10925583Speter		if (timerisset(&p->p_realtimer.it_value))
11025583Speter			timevaladd(&p->p_realtimer.it_value, &delta);
11126335Speter		if (p->p_sleepend)
11226335Speter			timevaladd(p->p_sleepend, &delta);
11326335Speter	}
11425583Speter	lease_updatetime(delta.tv_sec);
11525583Speter	splx(s);
11625583Speter	resettodr();
11725583Speter	return (0);
11825583Speter}
11925583Speter
12012221Sbde#ifndef _SYS_SYSPROTO_H_
12125583Speterstruct clock_gettime_args {
12225583Speter	clockid_t clock_id;
12325583Speter	struct	timespec *tp;
12425583Speter};
12525583Speter#endif
12625656Speter
12725583Speter/* ARGSUSED */
12825583Speterint
12930994Sphkclock_gettime(p, uap)
13025583Speter	struct proc *p;
13125583Speter	struct clock_gettime_args *uap;
13225583Speter{
13325583Speter	struct timespec ats;
13425583Speter
13525656Speter	if (SCARG(uap, clock_id) != CLOCK_REALTIME)
13625583Speter		return (EINVAL);
13733690Sphk	nanotime(&ats);
13825656Speter	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
14725656Speter
14825583Speter/* ARGSUSED */
14925583Speterint
15030994Sphkclock_settime(p, uap)
15125583Speter	struct proc *p;
15225583Speter	struct clock_settime_args *uap;
15325583Speter{
15425583Speter	struct timeval atv;
15525583Speter	struct timespec ats;
15625583Speter	int error;
15725583Speter
15825583Speter	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
15925583Speter		return (error);
16025656Speter	if (SCARG(uap, clock_id) != CLOCK_REALTIME)
16125583Speter		return (EINVAL);
16225583Speter	if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
16325583Speter		return (error);
16427855Sbde	if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000)
16525656Speter		return (EINVAL);
16634901Sphk	/* XXX Don't convert nsec->usec and back */
16725583Speter	TIMESPEC_TO_TIMEVAL(&atv, &ats);
16825583Speter	if ((error = settime(&atv)))
16925583Speter		return (error);
17025656Speter	return (0);
17125583Speter}
17225583Speter
17325583Speter#ifndef _SYS_SYSPROTO_H_
17425583Speterstruct clock_getres_args {
17525583Speter	clockid_t clock_id;
17625583Speter	struct	timespec *tp;
17725583Speter};
17825583Speter#endif
17925656Speter
18025583Speterint
18130994Sphkclock_getres(p, uap)
18225583Speter	struct proc *p;
18325583Speter	struct clock_getres_args *uap;
18425583Speter{
18525583Speter	struct timespec ts;
18625656Speter	int error;
18725583Speter
18825656Speter	if (SCARG(uap, clock_id) != CLOCK_REALTIME)
18925583Speter		return (EINVAL);
19025656Speter	error = 0;
19125583Speter	if (SCARG(uap, tp)) {
19225583Speter		ts.tv_sec = 0;
19333690Sphk		ts.tv_nsec = 1000000000 / timecounter->frequency;
19425656Speter		error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
19525583Speter	}
19625656Speter	return (error);
19725583Speter}
19825583Speter
19926335Speterstatic int nanowait;
20025656Speter
20126335Speterstatic int
20226335Speternanosleep1(p, rqt, rmt)
20325583Speter	struct proc *p;
20426335Speter	struct timespec *rqt, *rmt;
20525583Speter{
20628171Sache	struct timeval atv, utv, rtv;
20728171Sache	int error, s, timo, i, n;
20825583Speter
20928773Sbde	if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
21025656Speter		return (EINVAL);
21128773Sbde	if (rqt->tv_sec < 0 || rqt->tv_sec == 0 && rqt->tv_nsec == 0)
21228773Sbde		return (0);
21326335Speter	TIMESPEC_TO_TIMEVAL(&atv, rqt)
21425583Speter
21528171Sache	if (itimerfix(&atv)) {
21628171Sache		n = atv.tv_sec / 100000000;
21728171Sache		rtv = atv;
21828171Sache		rtv.tv_sec %= 100000000;
21928171Sache		(void)itimerfix(&rtv);
22028171Sache	} else
22128171Sache		n = 0;
22225583Speter
22328773Sbde	for (i = 0, error = EWOULDBLOCK; i <= n && error == EWOULDBLOCK; i++) {
22428171Sache		if (n > 0) {
22528171Sache			if (i == n)
22628171Sache				atv = rtv;
22728171Sache			else {
22828171Sache				atv.tv_sec = 100000000;
22928171Sache				atv.tv_usec = 0;
23028171Sache			}
23128171Sache		}
23234961Sphk		timo = tvtohz(&atv);
23328171Sache
23428171Sache		p->p_sleepend = &atv;
23528171Sache		error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", timo);
23628171Sache		p->p_sleepend = NULL;
23728171Sache		if (error == ERESTART)
23828171Sache			error = EINTR;
23928171Sache		if (rmt != NULL && (i == n || error != EWOULDBLOCK)) {
24028171Sache			/*-
24128171Sache			 * XXX this is unnecessary and possibly wrong if the timeout
24228171Sache			 * expired.  Then the remaining time should be zero.  If the
24328171Sache			 * calculation gives a nonzero value, then we have a bug.
24428171Sache			 * (1) if settimeofday() was called, then the calculation is
24528171Sache			 *     probably wrong, since `time' has probably become
24628171Sache			 *     inconsistent with the ending time `atv'.
24728171Sache			 *     XXX (1) should be fixed now with p->p_sleepend;
24828171Sache			 * (2) otherwise, our calculation of `timo' was wrong, perhaps
24928171Sache			 *     due to `tick' being wrong when hzto() was called or
25028171Sache			 *     changing afterwards (it can be wrong or change due to
25128171Sache			 *     hzto() not knowing about adjtime(2) or tickadj(8)).
25228171Sache			 *     Then we should be sleeping again instead instead of
25328171Sache			 *     returning.  Rounding up in hzto() probably fixes this
25428171Sache			 *     problem for small timeouts, but the absolute error may
25528171Sache			 *     be large for large timeouts.
25628171Sache			 */
25734961Sphk			getmicrotime(&utv);
25830606Sache			if (i != n) {
25930606Sache				atv.tv_sec += (n - i - 1) * 100000000;
26030606Sache				timevaladd(&atv, &rtv);
26130606Sache			}
26228171Sache			timevalsub(&atv, &utv);
26328171Sache			if (atv.tv_sec < 0)
26428171Sache				timerclear(&atv);
26528171Sache			TIMEVAL_TO_TIMESPEC(&atv, rmt);
26628171Sache		}
26726335Speter	}
26828171Sache	return (error == EWOULDBLOCK ? 0 : error);
26926335Speter}
27025583Speter
27126335Speter#ifndef _SYS_SYSPROTO_H_
27226335Speterstruct nanosleep_args {
27326335Speter	struct	timespec *rqtp;
27426335Speter	struct	timespec *rmtp;
27526335Speter};
27626335Speter#endif
27726335Speter
27826335Speter/* ARGSUSED */
27926335Speterint
28030994Sphknanosleep(p, uap)
28126335Speter	struct proc *p;
28226335Speter	struct nanosleep_args *uap;
28326335Speter{
28426335Speter	struct timespec rmt, rqt;
28526335Speter	int error, error2;
28626335Speter
28726335Speter	error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt));
28826335Speter	if (error)
28926335Speter		return (error);
29026336Speter	if (SCARG(uap, rmtp))
29126336Speter		if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE))
29226336Speter			return (EFAULT);
29326335Speter	error = nanosleep1(p, &rqt, &rmt);
29426335Speter	if (SCARG(uap, rmtp)) {
29525656Speter		error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
29626335Speter		if (error2)	/* XXX shouldn't happen, did useracc() above */
29725656Speter			return (error2);
29825583Speter	}
29925656Speter	return (error);
30025583Speter}
30125583Speter
30226335Speter#ifndef _SYS_SYSPROTO_H_
30326335Speterstruct signanosleep_args {
30426335Speter	struct	timespec *rqtp;
30526335Speter	struct	timespec *rmtp;
30626335Speter	sigset_t *mask;
30726335Speter};
30826335Speter#endif
30925583Speter
31026335Speter/* ARGSUSED */
31126335Speterint
31230994Sphksignanosleep(p, uap)
31326335Speter	struct proc *p;
31426335Speter	struct signanosleep_args *uap;
31526335Speter{
31626335Speter	struct timespec rmt, rqt;
31726335Speter	int error, error2;
31826335Speter	sigset_t mask;
31926335Speter
32026335Speter	error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt));
32126335Speter	if (error)
32226335Speter		return (error);
32326336Speter	if (SCARG(uap, rmtp))
32426336Speter		if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE))
32526336Speter			return (EFAULT);
32626335Speter	error = copyin(SCARG(uap, mask), &mask, sizeof(mask));
32726335Speter	if (error)
32826335Speter		return (error);
32926335Speter
33030440Speter	/* change mask for sleep */
33126335Speter	p->p_sigmask = mask &~ sigcantmask;
33226335Speter
33326335Speter	error = nanosleep1(p, &rqt, &rmt);
33426335Speter
33526335Speter	if (SCARG(uap, rmtp)) {
33626335Speter		error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
33726335Speter		if (error2)	/* XXX shouldn't happen, did useracc() above */
33826335Speter			return (error2);
33926335Speter	}
34026335Speter	return (error);
34126335Speter}
34226335Speter
34325583Speter#ifndef _SYS_SYSPROTO_H_
3441541Srgrimesstruct gettimeofday_args {
3451541Srgrimes	struct	timeval *tp;
3461541Srgrimes	struct	timezone *tzp;
3471541Srgrimes};
34812221Sbde#endif
3491541Srgrimes/* ARGSUSED */
3501549Srgrimesint
35130994Sphkgettimeofday(p, uap)
3521541Srgrimes	struct proc *p;
3531541Srgrimes	register struct gettimeofday_args *uap;
3541541Srgrimes{
3551541Srgrimes	struct timeval atv;
3561541Srgrimes	int error = 0;
3571541Srgrimes
3581541Srgrimes	if (uap->tp) {
3591541Srgrimes		microtime(&atv);
3603098Sphk		if ((error = copyout((caddr_t)&atv, (caddr_t)uap->tp,
3613098Sphk		    sizeof (atv))))
3621541Srgrimes			return (error);
3631541Srgrimes	}
3641541Srgrimes	if (uap->tzp)
3651541Srgrimes		error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
3661541Srgrimes		    sizeof (tz));
3671541Srgrimes	return (error);
3681541Srgrimes}
3691541Srgrimes
37012221Sbde#ifndef _SYS_SYSPROTO_H_
3711541Srgrimesstruct settimeofday_args {
3721541Srgrimes	struct	timeval *tv;
3731541Srgrimes	struct	timezone *tzp;
3741541Srgrimes};
37512221Sbde#endif
3761541Srgrimes/* ARGSUSED */
3771549Srgrimesint
37830994Sphksettimeofday(p, uap)
3791541Srgrimes	struct proc *p;
3801541Srgrimes	struct settimeofday_args *uap;
3811541Srgrimes{
38225656Speter	struct timeval atv;
3831541Srgrimes	struct timezone atz;
38425656Speter	int error;
3851541Srgrimes
3863098Sphk	if ((error = suser(p->p_ucred, &p->p_acflag)))
3871541Srgrimes		return (error);
3881541Srgrimes	/* Verify all parameters before changing time. */
38925656Speter	if (uap->tv) {
39025656Speter		if ((error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
39125656Speter		    sizeof(atv))))
39225656Speter			return (error);
39325656Speter		if (atv.tv_usec < 0 || atv.tv_usec >= 1000000)
39425656Speter			return (EINVAL);
39525656Speter	}
3961541Srgrimes	if (uap->tzp &&
3971541Srgrimes	    (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz))))
3981541Srgrimes		return (error);
39925583Speter	if (uap->tv && (error = settime(&atv)))
40025583Speter		return (error);
4011541Srgrimes	if (uap->tzp)
4021541Srgrimes		tz = atz;
4031541Srgrimes	return (0);
4041541Srgrimes}
4051541Srgrimes
4061541Srgrimesint	tickdelta;			/* current clock skew, us. per tick */
4071541Srgrimeslong	timedelta;			/* unapplied time correction, us. */
40812819Sphkstatic long	bigadj = 1000000;	/* use 10x skew above bigadj us. */
4091541Srgrimes
41012221Sbde#ifndef _SYS_SYSPROTO_H_
4111541Srgrimesstruct adjtime_args {
4121541Srgrimes	struct timeval *delta;
4131541Srgrimes	struct timeval *olddelta;
4141541Srgrimes};
41512221Sbde#endif
4161541Srgrimes/* ARGSUSED */
4171549Srgrimesint
41830994Sphkadjtime(p, uap)
4191541Srgrimes	struct proc *p;
4201541Srgrimes	register struct adjtime_args *uap;
4211541Srgrimes{
4221541Srgrimes	struct timeval atv;
4231541Srgrimes	register long ndelta, ntickdelta, odelta;
4241541Srgrimes	int s, error;
4251541Srgrimes
4263098Sphk	if ((error = suser(p->p_ucred, &p->p_acflag)))
4271541Srgrimes		return (error);
4283098Sphk	if ((error =
4293098Sphk	    copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval))))
4301541Srgrimes		return (error);
4311541Srgrimes
4321541Srgrimes	/*
4331541Srgrimes	 * Compute the total correction and the rate at which to apply it.
4341541Srgrimes	 * Round the adjustment down to a whole multiple of the per-tick
4351541Srgrimes	 * delta, so that after some number of incremental changes in
4361541Srgrimes	 * hardclock(), tickdelta will become zero, lest the correction
4371541Srgrimes	 * overshoot and start taking us away from the desired final time.
4381541Srgrimes	 */
4391541Srgrimes	ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
44017123Sbde	if (ndelta > bigadj || ndelta < -bigadj)
4411541Srgrimes		ntickdelta = 10 * tickadj;
4421541Srgrimes	else
4431541Srgrimes		ntickdelta = tickadj;
4441541Srgrimes	if (ndelta % ntickdelta)
4451541Srgrimes		ndelta = ndelta / ntickdelta * ntickdelta;
4461541Srgrimes
4471541Srgrimes	/*
4481541Srgrimes	 * To make hardclock()'s job easier, make the per-tick delta negative
4491541Srgrimes	 * if we want time to run slower; then hardclock can simply compute
4501541Srgrimes	 * tick + tickdelta, and subtract tickdelta from timedelta.
4511541Srgrimes	 */
4521541Srgrimes	if (ndelta < 0)
4531541Srgrimes		ntickdelta = -ntickdelta;
4541541Srgrimes	s = splclock();
4551541Srgrimes	odelta = timedelta;
4561541Srgrimes	timedelta = ndelta;
4571541Srgrimes	tickdelta = ntickdelta;
4581541Srgrimes	splx(s);
4591541Srgrimes
4601541Srgrimes	if (uap->olddelta) {
4611541Srgrimes		atv.tv_sec = odelta / 1000000;
4621541Srgrimes		atv.tv_usec = odelta % 1000000;
4631541Srgrimes		(void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta,
4641541Srgrimes		    sizeof(struct timeval));
4651541Srgrimes	}
4661541Srgrimes	return (0);
4671541Srgrimes}
4681541Srgrimes
4691541Srgrimes/*
4701541Srgrimes * Get value of an interval timer.  The process virtual and
4711541Srgrimes * profiling virtual time timers are kept in the p_stats area, since
4721541Srgrimes * they can be swapped out.  These are kept internally in the
4731541Srgrimes * way they are specified externally: in time until they expire.
4741541Srgrimes *
4751541Srgrimes * The real time interval timer is kept in the process table slot
4761541Srgrimes * for the process, and its value (it_value) is kept as an
4771541Srgrimes * absolute time rather than as a delta, so that it is easy to keep
4781541Srgrimes * periodic real-time signals from drifting.
4791541Srgrimes *
4801541Srgrimes * Virtual time timers are processed in the hardclock() routine of
4811541Srgrimes * kern_clock.c.  The real time timer is processed by a timeout
4821541Srgrimes * routine, called from the softclock() routine.  Since a callout
4831541Srgrimes * may be delayed in real time due to interrupt processing in the system,
4841541Srgrimes * it is possible for the real time timeout routine (realitexpire, given below),
4851541Srgrimes * to be delayed in real time past when it is supposed to occur.  It
4861541Srgrimes * does not suffice, therefore, to reload the real timer .it_value from the
4871541Srgrimes * real time timers .it_interval.  Rather, we compute the next time in
4881541Srgrimes * absolute time the timer should go off.
4891541Srgrimes */
49012221Sbde#ifndef _SYS_SYSPROTO_H_
4911541Srgrimesstruct getitimer_args {
4921541Srgrimes	u_int	which;
4931541Srgrimes	struct	itimerval *itv;
4941541Srgrimes};
49512221Sbde#endif
4961541Srgrimes/* ARGSUSED */
4971549Srgrimesint
49830994Sphkgetitimer(p, uap)
4991541Srgrimes	struct proc *p;
5001541Srgrimes	register struct getitimer_args *uap;
5011541Srgrimes{
50234961Sphk	struct timeval ctv;
5031541Srgrimes	struct itimerval aitv;
5041541Srgrimes	int s;
5051541Srgrimes
5061541Srgrimes	if (uap->which > ITIMER_PROF)
5071541Srgrimes		return (EINVAL);
50834961Sphk	s = splclock(); /* XXX still needed ? */
5091541Srgrimes	if (uap->which == ITIMER_REAL) {
5101541Srgrimes		/*
5111541Srgrimes		 * Convert from absoulte to relative time in .it_value
5121541Srgrimes		 * part of real time timer.  If time for real time timer
5131541Srgrimes		 * has passed return 0, else return difference between
5141541Srgrimes		 * current time and time for the timer to go off.
5151541Srgrimes		 */
5161541Srgrimes		aitv = p->p_realtimer;
51734961Sphk		if (timerisset(&aitv.it_value)) {
51834961Sphk			getmicrotime(&ctv);
51934961Sphk			if (timercmp(&aitv.it_value, &ctv, <))
5201541Srgrimes				timerclear(&aitv.it_value);
5211541Srgrimes			else
52234961Sphk				timevalsub(&aitv.it_value, &ctv);
52334961Sphk		}
5241541Srgrimes	} else
5251541Srgrimes		aitv = p->p_stats->p_timer[uap->which];
5261541Srgrimes	splx(s);
5271541Srgrimes	return (copyout((caddr_t)&aitv, (caddr_t)uap->itv,
5281541Srgrimes	    sizeof (struct itimerval)));
5291541Srgrimes}
5301541Srgrimes
53112221Sbde#ifndef _SYS_SYSPROTO_H_
5321541Srgrimesstruct setitimer_args {
5331541Srgrimes	u_int	which;
5341541Srgrimes	struct	itimerval *itv, *oitv;
5351541Srgrimes};
53612221Sbde#endif
5371541Srgrimes/* ARGSUSED */
5381549Srgrimesint
53930994Sphksetitimer(p, uap)
5401541Srgrimes	struct proc *p;
5411541Srgrimes	register struct setitimer_args *uap;
5421541Srgrimes{
5431541Srgrimes	struct itimerval aitv;
54434961Sphk	struct timeval ctv;
5451541Srgrimes	register struct itimerval *itvp;
5461541Srgrimes	int s, error;
5471541Srgrimes
5481541Srgrimes	if (uap->which > ITIMER_PROF)
5491541Srgrimes		return (EINVAL);
5501541Srgrimes	itvp = uap->itv;
5511541Srgrimes	if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
5521541Srgrimes	    sizeof(struct itimerval))))
5531541Srgrimes		return (error);
55412381Sbde	if ((uap->itv = uap->oitv) &&
55530994Sphk	    (error = getitimer(p, (struct getitimer_args *)uap)))
5561541Srgrimes		return (error);
5571541Srgrimes	if (itvp == 0)
5581541Srgrimes		return (0);
55928213Sache	if (itimerfix(&aitv.it_value))
5601541Srgrimes		return (EINVAL);
56128213Sache	if (!timerisset(&aitv.it_value))
56228213Sache		timerclear(&aitv.it_interval);
56328213Sache	else if (itimerfix(&aitv.it_interval))
56428213Sache		return (EINVAL);
56534961Sphk	s = splclock(); /* XXX: still needed ? */
5661541Srgrimes	if (uap->which == ITIMER_REAL) {
56729680Sgibbs		if (timerisset(&p->p_realtimer.it_value))
56829680Sgibbs			untimeout(realitexpire, (caddr_t)p, p->p_ithandle);
5691541Srgrimes		if (timerisset(&aitv.it_value)) {
57034961Sphk			getmicrotime(&ctv);
57134961Sphk			timevaladd(&aitv.it_value, &ctv);
57229680Sgibbs			p->p_ithandle = timeout(realitexpire, (caddr_t)p,
57329680Sgibbs						hzto(&aitv.it_value));
5741541Srgrimes		}
5751541Srgrimes		p->p_realtimer = aitv;
5761541Srgrimes	} else
5771541Srgrimes		p->p_stats->p_timer[uap->which] = aitv;
5781541Srgrimes	splx(s);
5791541Srgrimes	return (0);
5801541Srgrimes}
5811541Srgrimes
5821541Srgrimes/*
5831541Srgrimes * Real interval timer expired:
5841541Srgrimes * send process whose timer expired an alarm signal.
5851541Srgrimes * If time is not set up to reload, then just return.
5861541Srgrimes * Else compute next time timer should go off which is > current time.
5871541Srgrimes * This is where delay in processing this timeout causes multiple
5881541Srgrimes * SIGALRM calls to be compressed into one.
5899327Sbde * hzto() always adds 1 to allow for the time until the next clock
5909327Sbde * interrupt being strictly less than 1 clock tick, but we don't want
5919327Sbde * that here since we want to appear to be in sync with the clock
5929327Sbde * interrupt even when we're delayed.
5931541Srgrimes */
5941541Srgrimesvoid
5951541Srgrimesrealitexpire(arg)
5961541Srgrimes	void *arg;
5971541Srgrimes{
5981541Srgrimes	register struct proc *p;
59934961Sphk	struct timeval ctv;
6001541Srgrimes	int s;
6011541Srgrimes
6021541Srgrimes	p = (struct proc *)arg;
6031541Srgrimes	psignal(p, SIGALRM);
6041541Srgrimes	if (!timerisset(&p->p_realtimer.it_interval)) {
6051541Srgrimes		timerclear(&p->p_realtimer.it_value);
6061541Srgrimes		return;
6071541Srgrimes	}
6081541Srgrimes	for (;;) {
60934961Sphk		s = splclock(); /* XXX: still neeeded ? */
6101541Srgrimes		timevaladd(&p->p_realtimer.it_value,
6111541Srgrimes		    &p->p_realtimer.it_interval);
61234961Sphk		getmicrotime(&ctv);
61334961Sphk		if (timercmp(&p->p_realtimer.it_value, &ctv, >)) {
61429680Sgibbs			p->p_ithandle =
61529680Sgibbs			    timeout(realitexpire, (caddr_t)p,
61629680Sgibbs				    hzto(&p->p_realtimer.it_value) - 1);
6171541Srgrimes			splx(s);
6181541Srgrimes			return;
6191541Srgrimes		}
6201541Srgrimes		splx(s);
6211541Srgrimes	}
6221541Srgrimes}
6231541Srgrimes
6241541Srgrimes/*
6251541Srgrimes * Check that a proposed value to load into the .it_value or
6261541Srgrimes * .it_interval part of an interval timer is acceptable, and
6271541Srgrimes * fix it to have at least minimal value (i.e. if it is less
6281541Srgrimes * than the resolution of the clock, round it up.)
6291541Srgrimes */
6301549Srgrimesint
6311541Srgrimesitimerfix(tv)
6321541Srgrimes	struct timeval *tv;
6331541Srgrimes{
6341541Srgrimes
6351541Srgrimes	if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
6361541Srgrimes	    tv->tv_usec < 0 || tv->tv_usec >= 1000000)
6371541Srgrimes		return (EINVAL);
6381541Srgrimes	if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
6391541Srgrimes		tv->tv_usec = tick;
6401541Srgrimes	return (0);
6411541Srgrimes}
6421541Srgrimes
6431541Srgrimes/*
6441541Srgrimes * Decrement an interval timer by a specified number
6451541Srgrimes * of microseconds, which must be less than a second,
6461541Srgrimes * i.e. < 1000000.  If the timer expires, then reload
6471541Srgrimes * it.  In this case, carry over (usec - old value) to
6481541Srgrimes * reduce the value reloaded into the timer so that
6491541Srgrimes * the timer does not drift.  This routine assumes
6501541Srgrimes * that it is called in a context where the timers
6511541Srgrimes * on which it is operating cannot change in value.
6521541Srgrimes */
6531549Srgrimesint
6541541Srgrimesitimerdecr(itp, usec)
6551541Srgrimes	register struct itimerval *itp;
6561541Srgrimes	int usec;
6571541Srgrimes{
6581541Srgrimes
6591541Srgrimes	if (itp->it_value.tv_usec < usec) {
6601541Srgrimes		if (itp->it_value.tv_sec == 0) {
6611541Srgrimes			/* expired, and already in next interval */
6621541Srgrimes			usec -= itp->it_value.tv_usec;
6631541Srgrimes			goto expire;
6641541Srgrimes		}
6651541Srgrimes		itp->it_value.tv_usec += 1000000;
6661541Srgrimes		itp->it_value.tv_sec--;
6671541Srgrimes	}
6681541Srgrimes	itp->it_value.tv_usec -= usec;
6691541Srgrimes	usec = 0;
6701541Srgrimes	if (timerisset(&itp->it_value))
6711541Srgrimes		return (1);
6721541Srgrimes	/* expired, exactly at end of interval */
6731541Srgrimesexpire:
6741541Srgrimes	if (timerisset(&itp->it_interval)) {
6751541Srgrimes		itp->it_value = itp->it_interval;
6761541Srgrimes		itp->it_value.tv_usec -= usec;
6771541Srgrimes		if (itp->it_value.tv_usec < 0) {
6781541Srgrimes			itp->it_value.tv_usec += 1000000;
6791541Srgrimes			itp->it_value.tv_sec--;
6801541Srgrimes		}
6811541Srgrimes	} else
6821541Srgrimes		itp->it_value.tv_usec = 0;		/* sec is already 0 */
6831541Srgrimes	return (0);
6841541Srgrimes}
6851541Srgrimes
6861541Srgrimes/*
6871541Srgrimes * Add and subtract routines for timevals.
6881541Srgrimes * N.B.: subtract routine doesn't deal with
6891541Srgrimes * results which are before the beginning,
6901541Srgrimes * it just gets very confused in this case.
6911541Srgrimes * Caveat emptor.
6921541Srgrimes */
6931549Srgrimesvoid
6941541Srgrimestimevaladd(t1, t2)
6951541Srgrimes	struct timeval *t1, *t2;
6961541Srgrimes{
6971541Srgrimes
6981541Srgrimes	t1->tv_sec += t2->tv_sec;
6991541Srgrimes	t1->tv_usec += t2->tv_usec;
7001541Srgrimes	timevalfix(t1);
7011541Srgrimes}
7021541Srgrimes
7031549Srgrimesvoid
7041541Srgrimestimevalsub(t1, t2)
7051541Srgrimes	struct timeval *t1, *t2;
7061541Srgrimes{
7071541Srgrimes
7081541Srgrimes	t1->tv_sec -= t2->tv_sec;
7091541Srgrimes	t1->tv_usec -= t2->tv_usec;
7101541Srgrimes	timevalfix(t1);
7111541Srgrimes}
7121541Srgrimes
71312819Sphkstatic void
7141541Srgrimestimevalfix(t1)
7151541Srgrimes	struct timeval *t1;
7161541Srgrimes{
7171541Srgrimes
7181541Srgrimes	if (t1->tv_usec < 0) {
7191541Srgrimes		t1->tv_sec--;
7201541Srgrimes		t1->tv_usec += 1000000;
7211541Srgrimes	}
7221541Srgrimes	if (t1->tv_usec >= 1000000) {
7231541Srgrimes		t1->tv_sec++;
7241541Srgrimes		t1->tv_usec -= 1000000;
7251541Srgrimes	}
7261541Srgrimes}
727