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