xref: /original-bsd/sys/kern/kern_time.c (revision de436421)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)kern_time.c	8.4 (Berkeley) 05/26/95
8  */
9 
10 #include <sys/param.h>
11 #include <sys/resourcevar.h>
12 #include <sys/kernel.h>
13 #include <sys/systm.h>
14 #include <sys/proc.h>
15 #include <sys/vnode.h>
16 
17 #include <sys/mount.h>
18 #include <sys/syscallargs.h>
19 
20 #include <machine/cpu.h>
21 
22 /*
23  * Time of day and interval timer support.
24  *
25  * These routines provide the kernel entry points to get and set
26  * the time-of-day and per-process interval timers.  Subroutines
27  * here provide support for adding and subtracting timeval structures
28  * and decrementing interval timers, optionally reloading the interval
29  * timers when they expire.
30  */
31 
32 /* ARGSUSED */
33 int
34 gettimeofday(p, uap, retval)
35 	struct proc *p;
36 	register struct gettimeofday_args /* {
37 		syscallarg(struct timeval *) tp;
38 		syscallarg(struct timezone *) tzp;
39 	} */ *uap;
40 	register_t *retval;
41 {
42 	struct timeval atv;
43 	int error = 0;
44 
45 	if (SCARG(uap, tp)) {
46 		microtime(&atv);
47 		if (error = copyout((caddr_t)&atv, (caddr_t)SCARG(uap, tp),
48 		    sizeof (atv)))
49 			return (error);
50 	}
51 	if (SCARG(uap, tzp))
52 		error = copyout((caddr_t)&tz, (caddr_t)SCARG(uap, tzp),
53 		    sizeof (tz));
54 	return (error);
55 }
56 
57 /* ARGSUSED */
58 int
59 settimeofday(p, uap, retval)
60 	struct proc *p;
61 	struct settimeofday_args /* {
62 		syscallarg(struct timeval *) tv;
63 		syscallarg(struct timezone *) tzp;
64 	} */ *uap;
65 	register_t *retval;
66 {
67 	struct timeval atv, delta;
68 	struct timezone atz;
69 	int error, s;
70 
71 	if (error = suser(p->p_ucred, &p->p_acflag))
72 		return (error);
73 	/* Verify all parameters before changing time. */
74 	if (SCARG(uap, tv) && (error = copyin((caddr_t)SCARG(uap, tv),
75 	    (caddr_t)&atv, sizeof(atv))))
76 		return (error);
77 	if (SCARG(uap, tzp) && (error = copyin((caddr_t)SCARG(uap, tzp),
78 	    (caddr_t)&atz, sizeof(atz))))
79 		return (error);
80 	if (SCARG(uap, tv)) {
81 		/*
82 		 * If the system is secure, we do not allow the time to be
83 		 * set to an earlier value (it may be slowed using adjtime,
84 		 * but not set back). This feature prevent interlopers from
85 		 * setting arbitrary time stamps on files.
86 		 */
87 		if (securelevel > 0 && timercmp(&atv, &time, <))
88 			return (EPERM);
89 		/* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
90 		s = splclock();
91 		/* nb. delta.tv_usec may be < 0, but this is OK here */
92 		delta.tv_sec = atv.tv_sec - time.tv_sec;
93 		delta.tv_usec = atv.tv_usec - time.tv_usec;
94 		time = atv;
95 		(void) splsoftclock();
96 		timevaladd(&boottime, &delta);
97 		timevalfix(&boottime);
98 		timevaladd(&runtime, &delta);
99 		timevalfix(&runtime);
100 #		ifdef NFS
101 			lease_updatetime(delta.tv_sec);
102 #		endif
103 		splx(s);
104 		resettodr();
105 	}
106 	if (SCARG(uap, tzp))
107 		tz = atz;
108 	return (0);
109 }
110 
111 extern	int tickadj;			/* "standard" clock skew, us./tick */
112 int	tickdelta;			/* current clock skew, us. per tick */
113 long	timedelta;			/* unapplied time correction, us. */
114 long	bigadj = 1000000;		/* use 10x skew above bigadj us. */
115 
116 /* ARGSUSED */
117 int
118 adjtime(p, uap, retval)
119 	struct proc *p;
120 	register struct adjtime_args /* {
121 		syscallarg(struct timeval *) delta;
122 		syscallarg(struct timeval *) olddelta;
123 	} */ *uap;
124 	register_t *retval;
125 {
126 	struct timeval atv;
127 	register long ndelta, ntickdelta, odelta;
128 	int s, error;
129 
130 	if (error = suser(p->p_ucred, &p->p_acflag))
131 		return (error);
132 	if (error = copyin((caddr_t)SCARG(uap, delta), (caddr_t)&atv,
133 	    sizeof(struct timeval)))
134 		return (error);
135 
136 	/*
137 	 * Compute the total correction and the rate at which to apply it.
138 	 * Round the adjustment down to a whole multiple of the per-tick
139 	 * delta, so that after some number of incremental changes in
140 	 * hardclock(), tickdelta will become zero, lest the correction
141 	 * overshoot and start taking us away from the desired final time.
142 	 */
143 	ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
144 	if (ndelta > bigadj)
145 		ntickdelta = 10 * tickadj;
146 	else
147 		ntickdelta = tickadj;
148 	if (ndelta % ntickdelta)
149 		ndelta = ndelta / ntickdelta * ntickdelta;
150 
151 	/*
152 	 * To make hardclock()'s job easier, make the per-tick delta negative
153 	 * if we want time to run slower; then hardclock can simply compute
154 	 * tick + tickdelta, and subtract tickdelta from timedelta.
155 	 */
156 	if (ndelta < 0)
157 		ntickdelta = -ntickdelta;
158 	s = splclock();
159 	odelta = timedelta;
160 	timedelta = ndelta;
161 	tickdelta = ntickdelta;
162 	splx(s);
163 
164 	if (SCARG(uap, olddelta)) {
165 		atv.tv_sec = odelta / 1000000;
166 		atv.tv_usec = odelta % 1000000;
167 		(void) copyout((caddr_t)&atv, (caddr_t)SCARG(uap, olddelta),
168 		    sizeof(struct timeval));
169 	}
170 	return (0);
171 }
172 
173 /*
174  * Get value of an interval timer.  The process virtual and
175  * profiling virtual time timers are kept in the p_stats area, since
176  * they can be swapped out.  These are kept internally in the
177  * way they are specified externally: in time until they expire.
178  *
179  * The real time interval timer is kept in the process table slot
180  * for the process, and its value (it_value) is kept as an
181  * absolute time rather than as a delta, so that it is easy to keep
182  * periodic real-time signals from drifting.
183  *
184  * Virtual time timers are processed in the hardclock() routine of
185  * kern_clock.c.  The real time timer is processed by a timeout
186  * routine, called from the softclock() routine.  Since a callout
187  * may be delayed in real time due to interrupt processing in the system,
188  * it is possible for the real time timeout routine (realitexpire, given below),
189  * to be delayed in real time past when it is supposed to occur.  It
190  * does not suffice, therefore, to reload the real timer .it_value from the
191  * real time timers .it_interval.  Rather, we compute the next time in
192  * absolute time the timer should go off.
193  */
194 /* ARGSUSED */
195 int
196 getitimer(p, uap, retval)
197 	struct proc *p;
198 	register struct getitimer_args /* {
199 		syscallarg(u_int) which;
200 		syscallarg(struct itimerval *) itv;
201 	} */ *uap;
202 	register_t *retval;
203 {
204 	struct itimerval aitv;
205 	int s;
206 
207 	if (SCARG(uap, which) > ITIMER_PROF)
208 		return (EINVAL);
209 	s = splclock();
210 	if (SCARG(uap, which) == ITIMER_REAL) {
211 		/*
212 		 * Convert from absolute to relative time in .it_value
213 		 * part of real time timer.  If time for real time timer
214 		 * has passed return 0, else return difference between
215 		 * current time and time for the timer to go off.
216 		 */
217 		aitv = p->p_realtimer;
218 		if (timerisset(&aitv.it_value))
219 			if (timercmp(&aitv.it_value, &time, <))
220 				timerclear(&aitv.it_value);
221 			else
222 				timevalsub(&aitv.it_value,
223 				    (struct timeval *)&time);
224 	} else
225 		aitv = p->p_stats->p_timer[SCARG(uap, which)];
226 	splx(s);
227 	return (copyout((caddr_t)&aitv, (caddr_t)SCARG(uap, itv),
228 	    sizeof (struct itimerval)));
229 }
230 
231 /* ARGSUSED */
232 int
233 setitimer(p, uap, retval)
234 	struct proc *p;
235 	register struct setitimer_args /* {
236 		syscallarg(u_int) which;
237 		syscallarg(struct itimerval *) itv;
238 		syscallarg(struct itimerval *) oitv;
239 	} */ *uap;
240 	register_t *retval;
241 {
242 	struct itimerval aitv;
243 	register struct itimerval *itvp;
244 	int s, error;
245 
246 	if (SCARG(uap, which) > ITIMER_PROF)
247 		return (EINVAL);
248 	itvp = SCARG(uap, itv);
249 	if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
250 	    sizeof(struct itimerval))))
251 		return (error);
252 	if ((SCARG(uap, itv) = SCARG(uap, oitv)) &&
253 	    (error = getitimer(p, uap, retval)))
254 		return (error);
255 	if (itvp == 0)
256 		return (0);
257 	if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
258 		return (EINVAL);
259 	s = splclock();
260 	if (SCARG(uap, which) == ITIMER_REAL) {
261 		untimeout(realitexpire, (caddr_t)p);
262 		if (timerisset(&aitv.it_value)) {
263 			timevaladd(&aitv.it_value, (struct timeval *)&time);
264 			timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value));
265 		}
266 		p->p_realtimer = aitv;
267 	} else
268 		p->p_stats->p_timer[SCARG(uap, which)] = aitv;
269 	splx(s);
270 	return (0);
271 }
272 
273 /*
274  * Real interval timer expired:
275  * send process whose timer expired an alarm signal.
276  * If time is not set up to reload, then just return.
277  * Else compute next time timer should go off which is > current time.
278  * This is where delay in processing this timeout causes multiple
279  * SIGALRM calls to be compressed into one.
280  */
281 void
282 realitexpire(arg)
283 	void *arg;
284 {
285 	register struct proc *p;
286 	int s;
287 
288 	p = (struct proc *)arg;
289 	psignal(p, SIGALRM);
290 	if (!timerisset(&p->p_realtimer.it_interval)) {
291 		timerclear(&p->p_realtimer.it_value);
292 		return;
293 	}
294 	for (;;) {
295 		s = splclock();
296 		timevaladd(&p->p_realtimer.it_value,
297 		    &p->p_realtimer.it_interval);
298 		if (timercmp(&p->p_realtimer.it_value, &time, >)) {
299 			timeout(realitexpire, (caddr_t)p,
300 			    hzto(&p->p_realtimer.it_value));
301 			splx(s);
302 			return;
303 		}
304 		splx(s);
305 	}
306 }
307 
308 /*
309  * Check that a proposed value to load into the .it_value or
310  * .it_interval part of an interval timer is acceptable, and
311  * fix it to have at least minimal value (i.e. if it is less
312  * than the resolution of the clock, round it up.)
313  */
314 int
315 itimerfix(tv)
316 	struct timeval *tv;
317 {
318 
319 	if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
320 	    tv->tv_usec < 0 || tv->tv_usec >= 1000000)
321 		return (EINVAL);
322 	if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
323 		tv->tv_usec = tick;
324 	return (0);
325 }
326 
327 /*
328  * Decrement an interval timer by a specified number
329  * of microseconds, which must be less than a second,
330  * i.e. < 1000000.  If the timer expires, then reload
331  * it.  In this case, carry over (usec - old value) to
332  * reduce the value reloaded into the timer so that
333  * the timer does not drift.  This routine assumes
334  * that it is called in a context where the timers
335  * on which it is operating cannot change in value.
336  */
337 int
338 itimerdecr(itp, usec)
339 	register struct itimerval *itp;
340 	int usec;
341 {
342 
343 	if (itp->it_value.tv_usec < usec) {
344 		if (itp->it_value.tv_sec == 0) {
345 			/* expired, and already in next interval */
346 			usec -= itp->it_value.tv_usec;
347 			goto expire;
348 		}
349 		itp->it_value.tv_usec += 1000000;
350 		itp->it_value.tv_sec--;
351 	}
352 	itp->it_value.tv_usec -= usec;
353 	usec = 0;
354 	if (timerisset(&itp->it_value))
355 		return (1);
356 	/* expired, exactly at end of interval */
357 expire:
358 	if (timerisset(&itp->it_interval)) {
359 		itp->it_value = itp->it_interval;
360 		itp->it_value.tv_usec -= usec;
361 		if (itp->it_value.tv_usec < 0) {
362 			itp->it_value.tv_usec += 1000000;
363 			itp->it_value.tv_sec--;
364 		}
365 	} else
366 		itp->it_value.tv_usec = 0;		/* sec is already 0 */
367 	return (0);
368 }
369 
370 /*
371  * Add and subtract routines for timevals.
372  * N.B.: subtract routine doesn't deal with
373  * results which are before the beginning,
374  * it just gets very confused in this case.
375  * Caveat emptor.
376  */
377 timevaladd(t1, t2)
378 	struct timeval *t1, *t2;
379 {
380 
381 	t1->tv_sec += t2->tv_sec;
382 	t1->tv_usec += t2->tv_usec;
383 	timevalfix(t1);
384 }
385 
386 timevalsub(t1, t2)
387 	struct timeval *t1, *t2;
388 {
389 
390 	t1->tv_sec -= t2->tv_sec;
391 	t1->tv_usec -= t2->tv_usec;
392 	timevalfix(t1);
393 }
394 
395 timevalfix(t1)
396 	struct timeval *t1;
397 {
398 
399 	if (t1->tv_usec < 0) {
400 		t1->tv_sec--;
401 		t1->tv_usec += 1000000;
402 	}
403 	if (t1->tv_usec >= 1000000) {
404 		t1->tv_sec++;
405 		t1->tv_usec -= 1000000;
406 	}
407 }
408