xref: /csrg-svn/sys/kern/kern_time.c (revision 44405)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  *	@(#)kern_time.c	7.12 (Berkeley) 06/28/90
18  */
19 
20 #include "param.h"
21 #include "user.h"
22 #include "kernel.h"
23 #include "proc.h"
24 
25 #include "machine/reg.h"
26 #include "machine/cpu.h"
27 
28 /*
29  * Time of day and interval timer support.
30  *
31  * These routines provide the kernel entry points to get and set
32  * the time-of-day and per-process interval timers.  Subroutines
33  * here provide support for adding and subtracting timeval structures
34  * and decrementing interval timers, optionally reloading the interval
35  * timers when they expire.
36  */
37 
38 /* ARGSUSED */
39 gettimeofday(p, uap, retval)
40 	struct proc *p;
41 	register struct args {
42 		struct	timeval *tp;
43 		struct	timezone *tzp;
44 	} *uap;
45 	int *retval;
46 {
47 	struct timeval atv;
48 	int error = 0;
49 
50 	if (uap->tp) {
51 		microtime(&atv);
52 		if (error = copyout((caddr_t)&atv, (caddr_t)uap->tp,
53 		    sizeof (atv)))
54 			return (error);
55 	}
56 	if (uap->tzp)
57 		error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
58 		    sizeof (tz));
59 	return (error);
60 }
61 
62 settimeofday(p, uap, retval)
63 	struct proc *p;
64 	struct args {
65 		struct	timeval *tv;
66 		struct	timezone *tzp;
67 	} *uap;
68 	int *retval;
69 {
70 	struct timeval atv;
71 	struct timezone atz;
72 	int error, s;
73 
74 	if (error = suser(u.u_cred, &u.u_acflag))
75 		return (error);
76 	if (uap->tv) {
77 		if (error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
78 		    sizeof (struct timeval)))
79 			return (error);
80 		/* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
81 		boottime.tv_sec += atv.tv_sec - time.tv_sec;
82 		s = splhigh(); time = atv; splx(s);
83 		resettodr();
84 	}
85 	if (uap->tzp && (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz,
86 	    sizeof (atz))) == 0)
87 		tz = atz;
88 	return (error);
89 }
90 
91 extern	int tickadj;			/* "standard" clock skew, us./tick */
92 int	tickdelta;			/* current clock skew, us. per tick */
93 long	timedelta;			/* unapplied time correction, us. */
94 long	bigadj = 1000000;		/* use 10x skew above bigadj us. */
95 
96 /* ARGSUSED */
97 adjtime(p, uap, retval)
98 	struct proc *p;
99 	register struct args {
100 		struct timeval *delta;
101 		struct timeval *olddelta;
102 	} *uap;
103 	int *retval;
104 {
105 	struct timeval atv, oatv;
106 	register long ndelta;
107 	int s, error;
108 
109 	if (error = suser(u.u_cred, &u.u_acflag))
110 		return (error);
111 	if (error =
112 	    copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof (struct timeval)))
113 		return (error);
114 	ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
115 	if (timedelta == 0)
116 		if (ndelta > bigadj)
117 			tickdelta = 10 * tickadj;
118 		else
119 			tickdelta = tickadj;
120 	if (ndelta % tickdelta)
121 		ndelta = ndelta / tickadj * tickadj;
122 
123 	s = splclock();
124 	if (uap->olddelta) {
125 		oatv.tv_sec = timedelta / 1000000;
126 		oatv.tv_usec = timedelta % 1000000;
127 	}
128 	timedelta = ndelta;
129 	splx(s);
130 
131 	if (uap->olddelta)
132 		(void) copyout((caddr_t)&oatv, (caddr_t)uap->olddelta,
133 			sizeof (struct timeval));
134 	return (0);
135 }
136 
137 /*
138  * Get value of an interval timer.  The process virtual and
139  * profiling virtual time timers are kept in the u. area, since
140  * they can be swapped out.  These are kept internally in the
141  * way they are specified externally: in time until they expire.
142  *
143  * The real time interval timer is kept in the process table slot
144  * for the process, and its value (it_value) is kept as an
145  * absolute time rather than as a delta, so that it is easy to keep
146  * periodic real-time signals from drifting.
147  *
148  * Virtual time timers are processed in the hardclock() routine of
149  * kern_clock.c.  The real time timer is processed by a timeout
150  * routine, called from the softclock() routine.  Since a callout
151  * may be delayed in real time due to interrupt processing in the system,
152  * it is possible for the real time timeout routine (realitexpire, given below),
153  * to be delayed in real time past when it is supposed to occur.  It
154  * does not suffice, therefore, to reload the real timer .it_value from the
155  * real time timers .it_interval.  Rather, we compute the next time in
156  * absolute time the timer should go off.
157  */
158 /* ARGSUSED */
159 getitimer(p, uap, retval)
160 	struct proc *p;
161 	register struct args {
162 		u_int	which;
163 		struct	itimerval *itv;
164 	} *uap;
165 	int *retval;
166 {
167 	struct itimerval aitv;
168 	int s;
169 
170 	if (uap->which > ITIMER_PROF)
171 		return (EINVAL);
172 	s = splclock();
173 	if (uap->which == ITIMER_REAL) {
174 		/*
175 		 * Convert from absoulte to relative time in .it_value
176 		 * part of real time timer.  If time for real time timer
177 		 * has passed return 0, else return difference between
178 		 * current time and time for the timer to go off.
179 		 */
180 		aitv = p->p_realtimer;
181 		if (timerisset(&aitv.it_value))
182 			if (timercmp(&aitv.it_value, &time, <))
183 				timerclear(&aitv.it_value);
184 			else
185 				timevalsub(&aitv.it_value, &time);
186 	} else
187 		aitv = u.u_timer[uap->which];
188 	splx(s);
189 	return (copyout((caddr_t)&aitv, (caddr_t)uap->itv,
190 	    sizeof (struct itimerval)));
191 }
192 
193 /* ARGSUSED */
194 setitimer(p, uap, retval)
195 	struct proc *p;
196 	register struct args {
197 		u_int	which;
198 		struct	itimerval *itv, *oitv;
199 	} *uap;
200 	int *retval;
201 {
202 	struct itimerval aitv;
203 	register struct itimerval *itvp;
204 	int s, error;
205 
206 	if (uap->which > ITIMER_PROF)
207 		return (EINVAL);
208 	itvp = uap->itv;
209 	if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
210 	    sizeof(struct itimerval))))
211 		return (error);
212 	if ((uap->itv = uap->oitv) && (error = getitimer(p, uap, retval)))
213 		return (error);
214 	if (itvp == 0)
215 		return (0);
216 	if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
217 		return (EINVAL);
218 	s = splclock();
219 	if (uap->which == ITIMER_REAL) {
220 		untimeout(realitexpire, (caddr_t)p);
221 		if (timerisset(&aitv.it_value)) {
222 			timevaladd(&aitv.it_value, &time);
223 			timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value));
224 		}
225 		p->p_realtimer = aitv;
226 	} else
227 		u.u_timer[uap->which] = aitv;
228 	splx(s);
229 	return (0);
230 }
231 
232 /*
233  * Real interval timer expired:
234  * send process whose timer expired an alarm signal.
235  * If time is not set up to reload, then just return.
236  * Else compute next time timer should go off which is > current time.
237  * This is where delay in processing this timeout causes multiple
238  * SIGALRM calls to be compressed into one.
239  */
240 realitexpire(p)
241 	register struct proc *p;
242 {
243 	int s;
244 
245 	psignal(p, SIGALRM);
246 	if (!timerisset(&p->p_realtimer.it_interval)) {
247 		timerclear(&p->p_realtimer.it_value);
248 		return;
249 	}
250 	for (;;) {
251 		s = splclock();
252 		timevaladd(&p->p_realtimer.it_value,
253 		    &p->p_realtimer.it_interval);
254 		if (timercmp(&p->p_realtimer.it_value, &time, >)) {
255 			timeout(realitexpire, (caddr_t)p,
256 			    hzto(&p->p_realtimer.it_value));
257 			splx(s);
258 			return;
259 		}
260 		splx(s);
261 	}
262 }
263 
264 /*
265  * Check that a proposed value to load into the .it_value or
266  * .it_interval part of an interval timer is acceptable, and
267  * fix it to have at least minimal value (i.e. if it is less
268  * than the resolution of the clock, round it up.)
269  */
270 itimerfix(tv)
271 	struct timeval *tv;
272 {
273 
274 	if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
275 	    tv->tv_usec < 0 || tv->tv_usec >= 1000000)
276 		return (EINVAL);
277 	if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
278 		tv->tv_usec = tick;
279 	return (0);
280 }
281 
282 /*
283  * Decrement an interval timer by a specified number
284  * of microseconds, which must be less than a second,
285  * i.e. < 1000000.  If the timer expires, then reload
286  * it.  In this case, carry over (usec - old value) to
287  * reducint the value reloaded into the timer so that
288  * the timer does not drift.  This routine assumes
289  * that it is called in a context where the timers
290  * on which it is operating cannot change in value.
291  */
292 itimerdecr(itp, usec)
293 	register struct itimerval *itp;
294 	int usec;
295 {
296 
297 	if (itp->it_value.tv_usec < usec) {
298 		if (itp->it_value.tv_sec == 0) {
299 			/* expired, and already in next interval */
300 			usec -= itp->it_value.tv_usec;
301 			goto expire;
302 		}
303 		itp->it_value.tv_usec += 1000000;
304 		itp->it_value.tv_sec--;
305 	}
306 	itp->it_value.tv_usec -= usec;
307 	usec = 0;
308 	if (timerisset(&itp->it_value))
309 		return (1);
310 	/* expired, exactly at end of interval */
311 expire:
312 	if (timerisset(&itp->it_interval)) {
313 		itp->it_value = itp->it_interval;
314 		itp->it_value.tv_usec -= usec;
315 		if (itp->it_value.tv_usec < 0) {
316 			itp->it_value.tv_usec += 1000000;
317 			itp->it_value.tv_sec--;
318 		}
319 	} else
320 		itp->it_value.tv_usec = 0;		/* sec is already 0 */
321 	return (0);
322 }
323 
324 /*
325  * Add and subtract routines for timevals.
326  * N.B.: subtract routine doesn't deal with
327  * results which are before the beginning,
328  * it just gets very confused in this case.
329  * Caveat emptor.
330  */
331 timevaladd(t1, t2)
332 	struct timeval *t1, *t2;
333 {
334 
335 	t1->tv_sec += t2->tv_sec;
336 	t1->tv_usec += t2->tv_usec;
337 	timevalfix(t1);
338 }
339 
340 timevalsub(t1, t2)
341 	struct timeval *t1, *t2;
342 {
343 
344 	t1->tv_sec -= t2->tv_sec;
345 	t1->tv_usec -= t2->tv_usec;
346 	timevalfix(t1);
347 }
348 
349 timevalfix(t1)
350 	struct timeval *t1;
351 {
352 
353 	if (t1->tv_usec < 0) {
354 		t1->tv_sec--;
355 		t1->tv_usec += 1000000;
356 	}
357 	if (t1->tv_usec >= 1000000) {
358 		t1->tv_sec++;
359 		t1->tv_usec -= 1000000;
360 	}
361 }
362