kern_time.c revision 35029
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
3435029Sphk * $Id: kern_time.c,v 1.44 1998/03/30 09:50:23 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);
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();
10526335Speter	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
10625583Speter		if (timerisset(&p->p_realtimer.it_value))
10725583Speter			timevaladd(&p->p_realtimer.it_value, &delta);
10826335Speter	}
10925583Speter	lease_updatetime(delta.tv_sec);
11025583Speter	splx(s);
11125583Speter	resettodr();
11225583Speter	return (0);
11325583Speter}
11425583Speter
11512221Sbde#ifndef _SYS_SYSPROTO_H_
11625583Speterstruct clock_gettime_args {
11725583Speter	clockid_t clock_id;
11825583Speter	struct	timespec *tp;
11925583Speter};
12025583Speter#endif
12125656Speter
12225583Speter/* ARGSUSED */
12325583Speterint
12430994Sphkclock_gettime(p, uap)
12525583Speter	struct proc *p;
12625583Speter	struct clock_gettime_args *uap;
12725583Speter{
12825583Speter	struct timespec ats;
12925583Speter
13025656Speter	if (SCARG(uap, clock_id) != CLOCK_REALTIME)
13125583Speter		return (EINVAL);
13233690Sphk	nanotime(&ats);
13325656Speter	return (copyout(&ats, SCARG(uap, tp), sizeof(ats)));
13425583Speter}
13525583Speter
13625583Speter#ifndef _SYS_SYSPROTO_H_
13725583Speterstruct clock_settime_args {
13825583Speter	clockid_t clock_id;
13925583Speter	const struct	timespec *tp;
14025583Speter};
14125583Speter#endif
14225656Speter
14325583Speter/* ARGSUSED */
14425583Speterint
14530994Sphkclock_settime(p, uap)
14625583Speter	struct proc *p;
14725583Speter	struct clock_settime_args *uap;
14825583Speter{
14925583Speter	struct timeval atv;
15025583Speter	struct timespec ats;
15125583Speter	int error;
15225583Speter
15325583Speter	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
15425583Speter		return (error);
15525656Speter	if (SCARG(uap, clock_id) != CLOCK_REALTIME)
15625583Speter		return (EINVAL);
15725583Speter	if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
15825583Speter		return (error);
15927855Sbde	if (ats.tv_nsec < 0 || ats.tv_nsec >= 1000000000)
16025656Speter		return (EINVAL);
16134901Sphk	/* XXX Don't convert nsec->usec and back */
16225583Speter	TIMESPEC_TO_TIMEVAL(&atv, &ats);
16325583Speter	if ((error = settime(&atv)))
16425583Speter		return (error);
16525656Speter	return (0);
16625583Speter}
16725583Speter
16825583Speter#ifndef _SYS_SYSPROTO_H_
16925583Speterstruct clock_getres_args {
17025583Speter	clockid_t clock_id;
17125583Speter	struct	timespec *tp;
17225583Speter};
17325583Speter#endif
17425656Speter
17525583Speterint
17630994Sphkclock_getres(p, uap)
17725583Speter	struct proc *p;
17825583Speter	struct clock_getres_args *uap;
17925583Speter{
18025583Speter	struct timespec ts;
18125656Speter	int error;
18225583Speter
18325656Speter	if (SCARG(uap, clock_id) != CLOCK_REALTIME)
18425583Speter		return (EINVAL);
18525656Speter	error = 0;
18625583Speter	if (SCARG(uap, tp)) {
18725583Speter		ts.tv_sec = 0;
18833690Sphk		ts.tv_nsec = 1000000000 / timecounter->frequency;
18925656Speter		error = copyout(&ts, SCARG(uap, tp), sizeof(ts));
19025583Speter	}
19125656Speter	return (error);
19225583Speter}
19325583Speter
19426335Speterstatic int nanowait;
19525656Speter
19626335Speterstatic int
19726335Speternanosleep1(p, rqt, rmt)
19825583Speter	struct proc *p;
19926335Speter	struct timespec *rqt, *rmt;
20025583Speter{
20135029Sphk	struct timespec ts, ts2;
20235029Sphk	int error, timo;
20325583Speter
20428773Sbde	if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
20525656Speter		return (EINVAL);
20628773Sbde	if (rqt->tv_sec < 0 || rqt->tv_sec == 0 && rqt->tv_nsec == 0)
20728773Sbde		return (0);
20825583Speter
20935029Sphk	getnanoruntime(&ts);
21035029Sphk	timespecadd(&ts, rqt);
21135029Sphk	error = 0;
21235029Sphk	while (1) {
21335029Sphk		getnanoruntime(&ts2);
21435029Sphk		if (timespeccmp(&ts2, &ts, >=))
21535029Sphk			break;
21635029Sphk		else if (ts2.tv_sec + 60 * 60 * 24 * hz < ts.tv_sec)
21735029Sphk			timo = 60 * 60 * 24 * hz;
21835029Sphk		else if (ts2.tv_sec + 2 < ts.tv_sec) {
21935029Sphk			/* Leave one second for the difference in tv_nsec */
22035029Sphk			timo = ts.tv_sec - ts2.tv_sec - 1;
22135029Sphk			timo *= hz;
22235029Sphk		} else {
22335029Sphk			timo = (ts.tv_sec - ts2.tv_sec) * 1000000000;
22435029Sphk			timo += ts.tv_nsec - ts2.tv_nsec;
22535029Sphk			timo /= (1000000000 / hz);
22635029Sphk			timo ++;
22728171Sache		}
22828171Sache		error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", timo);
22935029Sphk		if (error == ERESTART) {
23028171Sache			error = EINTR;
23135029Sphk			break;
23228171Sache		}
23326335Speter	}
23435029Sphk	if (rmt) {
23535029Sphk		*rmt = ts;
23635029Sphk		timespecsub(rmt, &ts2);
23735029Sphk	}
23835029Sphk	return(error);
23926335Speter}
24025583Speter
24126335Speter#ifndef _SYS_SYSPROTO_H_
24226335Speterstruct nanosleep_args {
24326335Speter	struct	timespec *rqtp;
24426335Speter	struct	timespec *rmtp;
24526335Speter};
24626335Speter#endif
24726335Speter
24826335Speter/* ARGSUSED */
24926335Speterint
25030994Sphknanosleep(p, uap)
25126335Speter	struct proc *p;
25226335Speter	struct nanosleep_args *uap;
25326335Speter{
25426335Speter	struct timespec rmt, rqt;
25526335Speter	int error, error2;
25626335Speter
25726335Speter	error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt));
25826335Speter	if (error)
25926335Speter		return (error);
26026336Speter	if (SCARG(uap, rmtp))
26126336Speter		if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE))
26226336Speter			return (EFAULT);
26326335Speter	error = nanosleep1(p, &rqt, &rmt);
26426335Speter	if (SCARG(uap, rmtp)) {
26525656Speter		error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
26626335Speter		if (error2)	/* XXX shouldn't happen, did useracc() above */
26725656Speter			return (error2);
26825583Speter	}
26925656Speter	return (error);
27025583Speter}
27125583Speter
27226335Speter#ifndef _SYS_SYSPROTO_H_
27326335Speterstruct signanosleep_args {
27426335Speter	struct	timespec *rqtp;
27526335Speter	struct	timespec *rmtp;
27626335Speter	sigset_t *mask;
27726335Speter};
27826335Speter#endif
27925583Speter
28026335Speter/* ARGSUSED */
28126335Speterint
28230994Sphksignanosleep(p, uap)
28326335Speter	struct proc *p;
28426335Speter	struct signanosleep_args *uap;
28526335Speter{
28626335Speter	struct timespec rmt, rqt;
28726335Speter	int error, error2;
28826335Speter	sigset_t mask;
28926335Speter
29026335Speter	error = copyin(SCARG(uap, rqtp), &rqt, sizeof(rqt));
29126335Speter	if (error)
29226335Speter		return (error);
29326336Speter	if (SCARG(uap, rmtp))
29426336Speter		if (!useracc((caddr_t)SCARG(uap, rmtp), sizeof(rmt), B_WRITE))
29526336Speter			return (EFAULT);
29626335Speter	error = copyin(SCARG(uap, mask), &mask, sizeof(mask));
29726335Speter	if (error)
29826335Speter		return (error);
29926335Speter
30030440Speter	/* change mask for sleep */
30126335Speter	p->p_sigmask = mask &~ sigcantmask;
30226335Speter
30326335Speter	error = nanosleep1(p, &rqt, &rmt);
30426335Speter
30526335Speter	if (SCARG(uap, rmtp)) {
30626335Speter		error2 = copyout(&rmt, SCARG(uap, rmtp), sizeof(rmt));
30726335Speter		if (error2)	/* XXX shouldn't happen, did useracc() above */
30826335Speter			return (error2);
30926335Speter	}
31026335Speter	return (error);
31126335Speter}
31226335Speter
31325583Speter#ifndef _SYS_SYSPROTO_H_
3141541Srgrimesstruct gettimeofday_args {
3151541Srgrimes	struct	timeval *tp;
3161541Srgrimes	struct	timezone *tzp;
3171541Srgrimes};
31812221Sbde#endif
3191541Srgrimes/* ARGSUSED */
3201549Srgrimesint
32130994Sphkgettimeofday(p, uap)
3221541Srgrimes	struct proc *p;
3231541Srgrimes	register struct gettimeofday_args *uap;
3241541Srgrimes{
3251541Srgrimes	struct timeval atv;
3261541Srgrimes	int error = 0;
3271541Srgrimes
3281541Srgrimes	if (uap->tp) {
3291541Srgrimes		microtime(&atv);
3303098Sphk		if ((error = copyout((caddr_t)&atv, (caddr_t)uap->tp,
3313098Sphk		    sizeof (atv))))
3321541Srgrimes			return (error);
3331541Srgrimes	}
3341541Srgrimes	if (uap->tzp)
3351541Srgrimes		error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
3361541Srgrimes		    sizeof (tz));
3371541Srgrimes	return (error);
3381541Srgrimes}
3391541Srgrimes
34012221Sbde#ifndef _SYS_SYSPROTO_H_
3411541Srgrimesstruct settimeofday_args {
3421541Srgrimes	struct	timeval *tv;
3431541Srgrimes	struct	timezone *tzp;
3441541Srgrimes};
34512221Sbde#endif
3461541Srgrimes/* ARGSUSED */
3471549Srgrimesint
34830994Sphksettimeofday(p, uap)
3491541Srgrimes	struct proc *p;
3501541Srgrimes	struct settimeofday_args *uap;
3511541Srgrimes{
35225656Speter	struct timeval atv;
3531541Srgrimes	struct timezone atz;
35425656Speter	int error;
3551541Srgrimes
3563098Sphk	if ((error = suser(p->p_ucred, &p->p_acflag)))
3571541Srgrimes		return (error);
3581541Srgrimes	/* Verify all parameters before changing time. */
35925656Speter	if (uap->tv) {
36025656Speter		if ((error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
36125656Speter		    sizeof(atv))))
36225656Speter			return (error);
36325656Speter		if (atv.tv_usec < 0 || atv.tv_usec >= 1000000)
36425656Speter			return (EINVAL);
36525656Speter	}
3661541Srgrimes	if (uap->tzp &&
3671541Srgrimes	    (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz, sizeof(atz))))
3681541Srgrimes		return (error);
36925583Speter	if (uap->tv && (error = settime(&atv)))
37025583Speter		return (error);
3711541Srgrimes	if (uap->tzp)
3721541Srgrimes		tz = atz;
3731541Srgrimes	return (0);
3741541Srgrimes}
3751541Srgrimes
3761541Srgrimesint	tickdelta;			/* current clock skew, us. per tick */
3771541Srgrimeslong	timedelta;			/* unapplied time correction, us. */
37812819Sphkstatic long	bigadj = 1000000;	/* use 10x skew above bigadj us. */
3791541Srgrimes
38012221Sbde#ifndef _SYS_SYSPROTO_H_
3811541Srgrimesstruct adjtime_args {
3821541Srgrimes	struct timeval *delta;
3831541Srgrimes	struct timeval *olddelta;
3841541Srgrimes};
38512221Sbde#endif
3861541Srgrimes/* ARGSUSED */
3871549Srgrimesint
38830994Sphkadjtime(p, uap)
3891541Srgrimes	struct proc *p;
3901541Srgrimes	register struct adjtime_args *uap;
3911541Srgrimes{
3921541Srgrimes	struct timeval atv;
3931541Srgrimes	register long ndelta, ntickdelta, odelta;
3941541Srgrimes	int s, error;
3951541Srgrimes
3963098Sphk	if ((error = suser(p->p_ucred, &p->p_acflag)))
3971541Srgrimes		return (error);
3983098Sphk	if ((error =
3993098Sphk	    copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof(struct timeval))))
4001541Srgrimes		return (error);
4011541Srgrimes
4021541Srgrimes	/*
4031541Srgrimes	 * Compute the total correction and the rate at which to apply it.
4041541Srgrimes	 * Round the adjustment down to a whole multiple of the per-tick
4051541Srgrimes	 * delta, so that after some number of incremental changes in
4061541Srgrimes	 * hardclock(), tickdelta will become zero, lest the correction
4071541Srgrimes	 * overshoot and start taking us away from the desired final time.
4081541Srgrimes	 */
4091541Srgrimes	ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
41017123Sbde	if (ndelta > bigadj || ndelta < -bigadj)
4111541Srgrimes		ntickdelta = 10 * tickadj;
4121541Srgrimes	else
4131541Srgrimes		ntickdelta = tickadj;
4141541Srgrimes	if (ndelta % ntickdelta)
4151541Srgrimes		ndelta = ndelta / ntickdelta * ntickdelta;
4161541Srgrimes
4171541Srgrimes	/*
4181541Srgrimes	 * To make hardclock()'s job easier, make the per-tick delta negative
4191541Srgrimes	 * if we want time to run slower; then hardclock can simply compute
4201541Srgrimes	 * tick + tickdelta, and subtract tickdelta from timedelta.
4211541Srgrimes	 */
4221541Srgrimes	if (ndelta < 0)
4231541Srgrimes		ntickdelta = -ntickdelta;
4241541Srgrimes	s = splclock();
4251541Srgrimes	odelta = timedelta;
4261541Srgrimes	timedelta = ndelta;
4271541Srgrimes	tickdelta = ntickdelta;
4281541Srgrimes	splx(s);
4291541Srgrimes
4301541Srgrimes	if (uap->olddelta) {
4311541Srgrimes		atv.tv_sec = odelta / 1000000;
4321541Srgrimes		atv.tv_usec = odelta % 1000000;
4331541Srgrimes		(void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta,
4341541Srgrimes		    sizeof(struct timeval));
4351541Srgrimes	}
4361541Srgrimes	return (0);
4371541Srgrimes}
4381541Srgrimes
4391541Srgrimes/*
4401541Srgrimes * Get value of an interval timer.  The process virtual and
4411541Srgrimes * profiling virtual time timers are kept in the p_stats area, since
4421541Srgrimes * they can be swapped out.  These are kept internally in the
4431541Srgrimes * way they are specified externally: in time until they expire.
4441541Srgrimes *
4451541Srgrimes * The real time interval timer is kept in the process table slot
4461541Srgrimes * for the process, and its value (it_value) is kept as an
4471541Srgrimes * absolute time rather than as a delta, so that it is easy to keep
4481541Srgrimes * periodic real-time signals from drifting.
4491541Srgrimes *
4501541Srgrimes * Virtual time timers are processed in the hardclock() routine of
4511541Srgrimes * kern_clock.c.  The real time timer is processed by a timeout
4521541Srgrimes * routine, called from the softclock() routine.  Since a callout
4531541Srgrimes * may be delayed in real time due to interrupt processing in the system,
4541541Srgrimes * it is possible for the real time timeout routine (realitexpire, given below),
4551541Srgrimes * to be delayed in real time past when it is supposed to occur.  It
4561541Srgrimes * does not suffice, therefore, to reload the real timer .it_value from the
4571541Srgrimes * real time timers .it_interval.  Rather, we compute the next time in
4581541Srgrimes * absolute time the timer should go off.
4591541Srgrimes */
46012221Sbde#ifndef _SYS_SYSPROTO_H_
4611541Srgrimesstruct getitimer_args {
4621541Srgrimes	u_int	which;
4631541Srgrimes	struct	itimerval *itv;
4641541Srgrimes};
46512221Sbde#endif
4661541Srgrimes/* ARGSUSED */
4671549Srgrimesint
46830994Sphkgetitimer(p, uap)
4691541Srgrimes	struct proc *p;
4701541Srgrimes	register struct getitimer_args *uap;
4711541Srgrimes{
47234961Sphk	struct timeval ctv;
4731541Srgrimes	struct itimerval aitv;
4741541Srgrimes	int s;
4751541Srgrimes
4761541Srgrimes	if (uap->which > ITIMER_PROF)
4771541Srgrimes		return (EINVAL);
47834961Sphk	s = splclock(); /* XXX still needed ? */
4791541Srgrimes	if (uap->which == ITIMER_REAL) {
4801541Srgrimes		/*
4811541Srgrimes		 * Convert from absoulte to relative time in .it_value
4821541Srgrimes		 * part of real time timer.  If time for real time timer
4831541Srgrimes		 * has passed return 0, else return difference between
4841541Srgrimes		 * current time and time for the timer to go off.
4851541Srgrimes		 */
4861541Srgrimes		aitv = p->p_realtimer;
48734961Sphk		if (timerisset(&aitv.it_value)) {
48834961Sphk			getmicrotime(&ctv);
48934961Sphk			if (timercmp(&aitv.it_value, &ctv, <))
4901541Srgrimes				timerclear(&aitv.it_value);
4911541Srgrimes			else
49234961Sphk				timevalsub(&aitv.it_value, &ctv);
49334961Sphk		}
4941541Srgrimes	} else
4951541Srgrimes		aitv = p->p_stats->p_timer[uap->which];
4961541Srgrimes	splx(s);
4971541Srgrimes	return (copyout((caddr_t)&aitv, (caddr_t)uap->itv,
4981541Srgrimes	    sizeof (struct itimerval)));
4991541Srgrimes}
5001541Srgrimes
50112221Sbde#ifndef _SYS_SYSPROTO_H_
5021541Srgrimesstruct setitimer_args {
5031541Srgrimes	u_int	which;
5041541Srgrimes	struct	itimerval *itv, *oitv;
5051541Srgrimes};
50612221Sbde#endif
5071541Srgrimes/* ARGSUSED */
5081549Srgrimesint
50930994Sphksetitimer(p, uap)
5101541Srgrimes	struct proc *p;
5111541Srgrimes	register struct setitimer_args *uap;
5121541Srgrimes{
5131541Srgrimes	struct itimerval aitv;
51434961Sphk	struct timeval ctv;
5151541Srgrimes	register struct itimerval *itvp;
5161541Srgrimes	int s, error;
5171541Srgrimes
5181541Srgrimes	if (uap->which > ITIMER_PROF)
5191541Srgrimes		return (EINVAL);
5201541Srgrimes	itvp = uap->itv;
5211541Srgrimes	if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
5221541Srgrimes	    sizeof(struct itimerval))))
5231541Srgrimes		return (error);
52412381Sbde	if ((uap->itv = uap->oitv) &&
52530994Sphk	    (error = getitimer(p, (struct getitimer_args *)uap)))
5261541Srgrimes		return (error);
5271541Srgrimes	if (itvp == 0)
5281541Srgrimes		return (0);
52928213Sache	if (itimerfix(&aitv.it_value))
5301541Srgrimes		return (EINVAL);
53128213Sache	if (!timerisset(&aitv.it_value))
53228213Sache		timerclear(&aitv.it_interval);
53328213Sache	else if (itimerfix(&aitv.it_interval))
53428213Sache		return (EINVAL);
53534961Sphk	s = splclock(); /* XXX: still needed ? */
5361541Srgrimes	if (uap->which == ITIMER_REAL) {
53729680Sgibbs		if (timerisset(&p->p_realtimer.it_value))
53829680Sgibbs			untimeout(realitexpire, (caddr_t)p, p->p_ithandle);
5391541Srgrimes		if (timerisset(&aitv.it_value)) {
54034961Sphk			getmicrotime(&ctv);
54134961Sphk			timevaladd(&aitv.it_value, &ctv);
54229680Sgibbs			p->p_ithandle = timeout(realitexpire, (caddr_t)p,
54329680Sgibbs						hzto(&aitv.it_value));
5441541Srgrimes		}
5451541Srgrimes		p->p_realtimer = aitv;
5461541Srgrimes	} else
5471541Srgrimes		p->p_stats->p_timer[uap->which] = aitv;
5481541Srgrimes	splx(s);
5491541Srgrimes	return (0);
5501541Srgrimes}
5511541Srgrimes
5521541Srgrimes/*
5531541Srgrimes * Real interval timer expired:
5541541Srgrimes * send process whose timer expired an alarm signal.
5551541Srgrimes * If time is not set up to reload, then just return.
5561541Srgrimes * Else compute next time timer should go off which is > current time.
5571541Srgrimes * This is where delay in processing this timeout causes multiple
5581541Srgrimes * SIGALRM calls to be compressed into one.
5599327Sbde * hzto() always adds 1 to allow for the time until the next clock
5609327Sbde * interrupt being strictly less than 1 clock tick, but we don't want
5619327Sbde * that here since we want to appear to be in sync with the clock
5629327Sbde * interrupt even when we're delayed.
5631541Srgrimes */
5641541Srgrimesvoid
5651541Srgrimesrealitexpire(arg)
5661541Srgrimes	void *arg;
5671541Srgrimes{
5681541Srgrimes	register struct proc *p;
56934961Sphk	struct timeval ctv;
5701541Srgrimes	int s;
5711541Srgrimes
5721541Srgrimes	p = (struct proc *)arg;
5731541Srgrimes	psignal(p, SIGALRM);
5741541Srgrimes	if (!timerisset(&p->p_realtimer.it_interval)) {
5751541Srgrimes		timerclear(&p->p_realtimer.it_value);
5761541Srgrimes		return;
5771541Srgrimes	}
5781541Srgrimes	for (;;) {
57934961Sphk		s = splclock(); /* XXX: still neeeded ? */
5801541Srgrimes		timevaladd(&p->p_realtimer.it_value,
5811541Srgrimes		    &p->p_realtimer.it_interval);
58234961Sphk		getmicrotime(&ctv);
58334961Sphk		if (timercmp(&p->p_realtimer.it_value, &ctv, >)) {
58429680Sgibbs			p->p_ithandle =
58529680Sgibbs			    timeout(realitexpire, (caddr_t)p,
58629680Sgibbs				    hzto(&p->p_realtimer.it_value) - 1);
5871541Srgrimes			splx(s);
5881541Srgrimes			return;
5891541Srgrimes		}
5901541Srgrimes		splx(s);
5911541Srgrimes	}
5921541Srgrimes}
5931541Srgrimes
5941541Srgrimes/*
5951541Srgrimes * Check that a proposed value to load into the .it_value or
5961541Srgrimes * .it_interval part of an interval timer is acceptable, and
5971541Srgrimes * fix it to have at least minimal value (i.e. if it is less
5981541Srgrimes * than the resolution of the clock, round it up.)
5991541Srgrimes */
6001549Srgrimesint
6011541Srgrimesitimerfix(tv)
6021541Srgrimes	struct timeval *tv;
6031541Srgrimes{
6041541Srgrimes
6051541Srgrimes	if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
6061541Srgrimes	    tv->tv_usec < 0 || tv->tv_usec >= 1000000)
6071541Srgrimes		return (EINVAL);
6081541Srgrimes	if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
6091541Srgrimes		tv->tv_usec = tick;
6101541Srgrimes	return (0);
6111541Srgrimes}
6121541Srgrimes
6131541Srgrimes/*
6141541Srgrimes * Decrement an interval timer by a specified number
6151541Srgrimes * of microseconds, which must be less than a second,
6161541Srgrimes * i.e. < 1000000.  If the timer expires, then reload
6171541Srgrimes * it.  In this case, carry over (usec - old value) to
6181541Srgrimes * reduce the value reloaded into the timer so that
6191541Srgrimes * the timer does not drift.  This routine assumes
6201541Srgrimes * that it is called in a context where the timers
6211541Srgrimes * on which it is operating cannot change in value.
6221541Srgrimes */
6231549Srgrimesint
6241541Srgrimesitimerdecr(itp, usec)
6251541Srgrimes	register struct itimerval *itp;
6261541Srgrimes	int usec;
6271541Srgrimes{
6281541Srgrimes
6291541Srgrimes	if (itp->it_value.tv_usec < usec) {
6301541Srgrimes		if (itp->it_value.tv_sec == 0) {
6311541Srgrimes			/* expired, and already in next interval */
6321541Srgrimes			usec -= itp->it_value.tv_usec;
6331541Srgrimes			goto expire;
6341541Srgrimes		}
6351541Srgrimes		itp->it_value.tv_usec += 1000000;
6361541Srgrimes		itp->it_value.tv_sec--;
6371541Srgrimes	}
6381541Srgrimes	itp->it_value.tv_usec -= usec;
6391541Srgrimes	usec = 0;
6401541Srgrimes	if (timerisset(&itp->it_value))
6411541Srgrimes		return (1);
6421541Srgrimes	/* expired, exactly at end of interval */
6431541Srgrimesexpire:
6441541Srgrimes	if (timerisset(&itp->it_interval)) {
6451541Srgrimes		itp->it_value = itp->it_interval;
6461541Srgrimes		itp->it_value.tv_usec -= usec;
6471541Srgrimes		if (itp->it_value.tv_usec < 0) {
6481541Srgrimes			itp->it_value.tv_usec += 1000000;
6491541Srgrimes			itp->it_value.tv_sec--;
6501541Srgrimes		}
6511541Srgrimes	} else
6521541Srgrimes		itp->it_value.tv_usec = 0;		/* sec is already 0 */
6531541Srgrimes	return (0);
6541541Srgrimes}
6551541Srgrimes
6561541Srgrimes/*
6571541Srgrimes * Add and subtract routines for timevals.
6581541Srgrimes * N.B.: subtract routine doesn't deal with
6591541Srgrimes * results which are before the beginning,
6601541Srgrimes * it just gets very confused in this case.
6611541Srgrimes * Caveat emptor.
6621541Srgrimes */
6631549Srgrimesvoid
6641541Srgrimestimevaladd(t1, t2)
6651541Srgrimes	struct timeval *t1, *t2;
6661541Srgrimes{
6671541Srgrimes
6681541Srgrimes	t1->tv_sec += t2->tv_sec;
6691541Srgrimes	t1->tv_usec += t2->tv_usec;
6701541Srgrimes	timevalfix(t1);
6711541Srgrimes}
6721541Srgrimes
6731549Srgrimesvoid
6741541Srgrimestimevalsub(t1, t2)
6751541Srgrimes	struct timeval *t1, *t2;
6761541Srgrimes{
6771541Srgrimes
6781541Srgrimes	t1->tv_sec -= t2->tv_sec;
6791541Srgrimes	t1->tv_usec -= t2->tv_usec;
6801541Srgrimes	timevalfix(t1);
6811541Srgrimes}
6821541Srgrimes
68312819Sphkstatic void
6841541Srgrimestimevalfix(t1)
6851541Srgrimes	struct timeval *t1;
6861541Srgrimes{
6871541Srgrimes
6881541Srgrimes	if (t1->tv_usec < 0) {
6891541Srgrimes		t1->tv_sec--;
6901541Srgrimes		t1->tv_usec += 1000000;
6911541Srgrimes	}
6921541Srgrimes	if (t1->tv_usec >= 1000000) {
6931541Srgrimes		t1->tv_sec++;
6941541Srgrimes		t1->tv_usec -= 1000000;
6951541Srgrimes	}
6961541Srgrimes}
697