kern_time.c revision 1.31 1 /* $NetBSD: kern_time.c,v 1.31 1998/02/19 00:51:38 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)kern_time.c 8.1 (Berkeley) 6/10/93
36 */
37
38 #include "fs_nfs.h"
39
40 #include <sys/param.h>
41 #include <sys/resourcevar.h>
42 #include <sys/kernel.h>
43 #include <sys/systm.h>
44 #include <sys/proc.h>
45 #include <sys/vnode.h>
46 #include <sys/signalvar.h>
47 #include <sys/syslog.h>
48
49 #include <sys/mount.h>
50 #include <sys/syscallargs.h>
51
52 #if defined(NFS) || defined(NFSSERVER)
53 #include <nfs/rpcv2.h>
54 #include <nfs/nfsproto.h>
55 #include <nfs/nfs_var.h>
56 #endif
57
58 #include <machine/cpu.h>
59
60 static int settime __P((struct timeval *));
61
62 /*
63 * Time of day and interval timer support.
64 *
65 * These routines provide the kernel entry points to get and set
66 * the time-of-day and per-process interval timers. Subroutines
67 * here provide support for adding and subtracting timeval structures
68 * and decrementing interval timers, optionally reloading the interval
69 * timers when they expire.
70 */
71
72 /* This function is used by clock_settime and settimeofday */
73 static int
74 settime(tv)
75 struct timeval *tv;
76 {
77 struct timeval delta;
78 int s;
79
80 /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
81 s = splclock();
82 timersub(tv, &time, &delta);
83 if ((delta.tv_sec < 0 || delta.tv_usec < 0) && securelevel > 1)
84 return (EPERM);
85 #ifdef notyet
86 if ((delta.tv_sec < 86400) && securelevel > 0)
87 return (EPERM);
88 #endif
89 time = *tv;
90 (void) splsoftclock();
91 timeradd(&boottime, &delta, &boottime);
92 timeradd(&runtime, &delta, &runtime);
93 # if defined(NFS) || defined(NFSSERVER)
94 nqnfs_lease_updatetime(delta.tv_sec);
95 # endif
96 splx(s);
97 resettodr();
98 return (0);
99 }
100
101 /* ARGSUSED */
102 int
103 sys_clock_gettime(p, v, retval)
104 struct proc *p;
105 void *v;
106 register_t *retval;
107 {
108 register struct sys_clock_gettime_args /* {
109 syscallarg(clockid_t) clock_id;
110 syscallarg(struct timespec *) tp;
111 } */ *uap = v;
112 clockid_t clock_id;
113 struct timeval atv;
114 struct timespec ats;
115
116 clock_id = SCARG(uap, clock_id);
117 if (clock_id != CLOCK_REALTIME)
118 return (EINVAL);
119
120 microtime(&atv);
121 TIMEVAL_TO_TIMESPEC(&atv,&ats);
122
123 return copyout(&ats, SCARG(uap, tp), sizeof(ats));
124 }
125
126 /* ARGSUSED */
127 int
128 sys_clock_settime(p, v, retval)
129 struct proc *p;
130 void *v;
131 register_t *retval;
132 {
133 register struct sys_clock_settime_args /* {
134 syscallarg(clockid_t) clock_id;
135 syscallarg(const struct timespec *) tp;
136 } */ *uap = v;
137 clockid_t clock_id;
138 struct timeval atv;
139 struct timespec ats;
140 int error;
141
142 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
143 return (error);
144
145 clock_id = SCARG(uap, clock_id);
146 if (clock_id != CLOCK_REALTIME)
147 return (EINVAL);
148
149 if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
150 return (error);
151
152 TIMESPEC_TO_TIMEVAL(&atv,&ats);
153 if ((error = settime(&atv)))
154 return (error);
155
156 return 0;
157 }
158
159 int
160 sys_clock_getres(p, v, retval)
161 struct proc *p;
162 void *v;
163 register_t *retval;
164 {
165 register struct sys_clock_getres_args /* {
166 syscallarg(clockid_t) clock_id;
167 syscallarg(struct timespec *) tp;
168 } */ *uap = v;
169 clockid_t clock_id;
170 struct timespec ts;
171 int error = 0;
172
173 clock_id = SCARG(uap, clock_id);
174 if (clock_id != CLOCK_REALTIME)
175 return (EINVAL);
176
177 if (SCARG(uap, tp)) {
178 ts.tv_sec = 0;
179 ts.tv_nsec = 1000000000 / hz;
180
181 error = copyout(&ts, SCARG(uap, tp), sizeof (ts));
182 }
183
184 return error;
185 }
186
187 /* ARGSUSED */
188 int
189 sys_nanosleep(p, v, retval)
190 struct proc *p;
191 void *v;
192 register_t *retval;
193 {
194 static int nanowait;
195 register struct sys_nanosleep_args/* {
196 syscallarg(struct timespec *) rqtp;
197 syscallarg(struct timespec *) rmtp;
198 } */ *uap = v;
199 struct timespec rqt;
200 struct timespec rmt;
201 struct timeval atv, utv;
202 int error, s, timo;
203
204 error = copyin((caddr_t)SCARG(uap, rqtp), (caddr_t)&rqt,
205 sizeof(struct timespec));
206 if (error)
207 return (error);
208
209 TIMESPEC_TO_TIMEVAL(&atv,&rqt)
210 if (itimerfix(&atv))
211 return (EINVAL);
212
213 s = splclock();
214 timeradd(&atv,&time,&atv);
215 timo = hzto(&atv);
216 /*
217 * Avoid inadvertantly sleeping forever
218 */
219 if (timo == 0)
220 timo = 1;
221 splx(s);
222
223 error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", timo);
224 if (error == ERESTART)
225 error = EINTR;
226 if (error == EWOULDBLOCK)
227 error = 0;
228
229 if (SCARG(uap, rmtp)) {
230 int error;
231
232 s = splclock();
233 utv = time;
234 splx(s);
235
236 timersub(&atv, &utv, &utv);
237 if (utv.tv_sec < 0)
238 timerclear(&utv);
239
240 TIMEVAL_TO_TIMESPEC(&utv,&rmt);
241 error = copyout((caddr_t)&rmt, (caddr_t)SCARG(uap,rmtp),
242 sizeof(rmt));
243 if (error)
244 return (error);
245 }
246
247 return error;
248 }
249
250 /* ARGSUSED */
251 int
252 sys_gettimeofday(p, v, retval)
253 struct proc *p;
254 void *v;
255 register_t *retval;
256 {
257 register struct sys_gettimeofday_args /* {
258 syscallarg(struct timeval *) tp;
259 syscallarg(struct timezone *) tzp;
260 } */ *uap = v;
261 struct timeval atv;
262 int error = 0;
263 struct timezone tzfake;
264
265 if (SCARG(uap, tp)) {
266 microtime(&atv);
267 error = copyout(&atv, SCARG(uap, tp), sizeof (atv));
268 if (error)
269 return (error);
270 }
271 if (SCARG(uap, tzp)) {
272 /*
273 * NetBSD has no kernel notion of timezone, so we just
274 * fake up a timezone struct and return it if demanded.
275 */
276 tzfake.tz_minuteswest = 0;
277 tzfake.tz_dsttime = 0;
278 error = copyout(&tzfake, SCARG(uap, tzp), sizeof (tzfake));
279 }
280 return (error);
281 }
282
283 /* ARGSUSED */
284 int
285 sys_settimeofday(p, v, retval)
286 struct proc *p;
287 void *v;
288 register_t *retval;
289 {
290 struct sys_settimeofday_args /* {
291 syscallarg(const struct timeval *) tv;
292 syscallarg(const struct timezone *) tzp;
293 } */ *uap = v;
294 struct timeval atv;
295 struct timezone atz;
296 int error;
297
298 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
299 return (error);
300 /* Verify all parameters before changing time. */
301 if (SCARG(uap, tv) && (error = copyin(SCARG(uap, tv),
302 &atv, sizeof(atv))))
303 return (error);
304 /* XXX since we don't use tz, probably no point in doing copyin. */
305 if (SCARG(uap, tzp) && (error = copyin(SCARG(uap, tzp),
306 &atz, sizeof(atz))))
307 return (error);
308 if (SCARG(uap, tv))
309 if ((error = settime(&atv)))
310 return (error);
311 /*
312 * NetBSD has no kernel notion of timezone, and only an
313 * obsolete program would try to set it, so we log a warning.
314 */
315 if (SCARG(uap, tzp))
316 log(LOG_WARNING, "pid %d attempted to set the "
317 "(obsolete) kernel timezone.", p->p_pid);
318 return (0);
319 }
320
321 int tickdelta; /* current clock skew, us. per tick */
322 long timedelta; /* unapplied time correction, us. */
323 long bigadj = 1000000; /* use 10x skew above bigadj us. */
324
325 /* ARGSUSED */
326 int
327 sys_adjtime(p, v, retval)
328 struct proc *p;
329 void *v;
330 register_t *retval;
331 {
332 register struct sys_adjtime_args /* {
333 syscallarg(const struct timeval *) delta;
334 syscallarg(struct timeval *) olddelta;
335 } */ *uap = v;
336 struct timeval atv;
337 register long ndelta, ntickdelta, odelta;
338 int s, error;
339
340 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
341 return (error);
342
343 error = copyin(SCARG(uap, delta), &atv, sizeof(struct timeval));
344 if (error)
345 return (error);
346
347 /*
348 * Compute the total correction and the rate at which to apply it.
349 * Round the adjustment down to a whole multiple of the per-tick
350 * delta, so that after some number of incremental changes in
351 * hardclock(), tickdelta will become zero, lest the correction
352 * overshoot and start taking us away from the desired final time.
353 */
354 ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
355 if (ndelta > bigadj)
356 ntickdelta = 10 * tickadj;
357 else
358 ntickdelta = tickadj;
359 if (ndelta % ntickdelta)
360 ndelta = ndelta / ntickdelta * ntickdelta;
361
362 /*
363 * To make hardclock()'s job easier, make the per-tick delta negative
364 * if we want time to run slower; then hardclock can simply compute
365 * tick + tickdelta, and subtract tickdelta from timedelta.
366 */
367 if (ndelta < 0)
368 ntickdelta = -ntickdelta;
369 s = splclock();
370 odelta = timedelta;
371 timedelta = ndelta;
372 tickdelta = ntickdelta;
373 splx(s);
374
375 if (SCARG(uap, olddelta)) {
376 atv.tv_sec = odelta / 1000000;
377 atv.tv_usec = odelta % 1000000;
378 (void) copyout(&atv, SCARG(uap, olddelta),
379 sizeof(struct timeval));
380 }
381 return (0);
382 }
383
384 /*
385 * Get value of an interval timer. The process virtual and
386 * profiling virtual time timers are kept in the p_stats area, since
387 * they can be swapped out. These are kept internally in the
388 * way they are specified externally: in time until they expire.
389 *
390 * The real time interval timer is kept in the process table slot
391 * for the process, and its value (it_value) is kept as an
392 * absolute time rather than as a delta, so that it is easy to keep
393 * periodic real-time signals from drifting.
394 *
395 * Virtual time timers are processed in the hardclock() routine of
396 * kern_clock.c. The real time timer is processed by a timeout
397 * routine, called from the softclock() routine. Since a callout
398 * may be delayed in real time due to interrupt processing in the system,
399 * it is possible for the real time timeout routine (realitexpire, given below),
400 * to be delayed in real time past when it is supposed to occur. It
401 * does not suffice, therefore, to reload the real timer .it_value from the
402 * real time timers .it_interval. Rather, we compute the next time in
403 * absolute time the timer should go off.
404 */
405 /* ARGSUSED */
406 int
407 sys_getitimer(p, v, retval)
408 struct proc *p;
409 void *v;
410 register_t *retval;
411 {
412 register struct sys_getitimer_args /* {
413 syscallarg(int) which;
414 syscallarg(struct itimerval *) itv;
415 } */ *uap = v;
416 int which = SCARG(uap, which);
417 struct itimerval aitv;
418 int s;
419
420 if ((u_int)which > ITIMER_PROF)
421 return (EINVAL);
422 s = splclock();
423 if (which == ITIMER_REAL) {
424 /*
425 * Convert from absolute to relative time in .it_value
426 * part of real time timer. If time for real time timer
427 * has passed return 0, else return difference between
428 * current time and time for the timer to go off.
429 */
430 aitv = p->p_realtimer;
431 if (timerisset(&aitv.it_value))
432 if (timercmp(&aitv.it_value, &time, <))
433 timerclear(&aitv.it_value);
434 else
435 timersub(&aitv.it_value, &time, &aitv.it_value);
436 } else
437 aitv = p->p_stats->p_timer[which];
438 splx(s);
439 return (copyout(&aitv, SCARG(uap, itv), sizeof (struct itimerval)));
440 }
441
442 /* ARGSUSED */
443 int
444 sys_setitimer(p, v, retval)
445 struct proc *p;
446 register void *v;
447 register_t *retval;
448 {
449 register struct sys_setitimer_args /* {
450 syscallarg(int) which;
451 syscallarg(const struct itimerval *) itv;
452 syscallarg(struct itimerval *) oitv;
453 } */ *uap = v;
454 int which = SCARG(uap, which);
455 struct sys_getitimer_args getargs;
456 struct itimerval aitv;
457 register const struct itimerval *itvp;
458 int s, error;
459
460 if ((u_int)which > ITIMER_PROF)
461 return (EINVAL);
462 itvp = SCARG(uap, itv);
463 if (itvp && (error = copyin(itvp, &aitv, sizeof(struct itimerval))))
464 return (error);
465 if (SCARG(uap, oitv) != NULL) {
466 SCARG(&getargs, which) = which;
467 SCARG(&getargs, itv) = SCARG(uap, oitv);
468 if ((error = sys_getitimer(p, &getargs, retval)) != 0)
469 return (error);
470 }
471 if (itvp == 0)
472 return (0);
473 if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
474 return (EINVAL);
475 s = splclock();
476 if (which == ITIMER_REAL) {
477 untimeout(realitexpire, p);
478 if (timerisset(&aitv.it_value)) {
479 timeradd(&aitv.it_value, &time, &aitv.it_value);
480 timeout(realitexpire, p, hzto(&aitv.it_value));
481 }
482 p->p_realtimer = aitv;
483 } else
484 p->p_stats->p_timer[which] = aitv;
485 splx(s);
486 return (0);
487 }
488
489 /*
490 * Real interval timer expired:
491 * send process whose timer expired an alarm signal.
492 * If time is not set up to reload, then just return.
493 * Else compute next time timer should go off which is > current time.
494 * This is where delay in processing this timeout causes multiple
495 * SIGALRM calls to be compressed into one.
496 */
497 void
498 realitexpire(arg)
499 void *arg;
500 {
501 register struct proc *p;
502 int s;
503
504 p = (struct proc *)arg;
505 psignal(p, SIGALRM);
506 if (!timerisset(&p->p_realtimer.it_interval)) {
507 timerclear(&p->p_realtimer.it_value);
508 return;
509 }
510 for (;;) {
511 s = splclock();
512 timeradd(&p->p_realtimer.it_value,
513 &p->p_realtimer.it_interval, &p->p_realtimer.it_value);
514 if (timercmp(&p->p_realtimer.it_value, &time, >)) {
515 timeout(realitexpire, p,
516 hzto(&p->p_realtimer.it_value));
517 splx(s);
518 return;
519 }
520 splx(s);
521 }
522 }
523
524 /*
525 * Check that a proposed value to load into the .it_value or
526 * .it_interval part of an interval timer is acceptable, and
527 * fix it to have at least minimal value (i.e. if it is less
528 * than the resolution of the clock, round it up.)
529 */
530 int
531 itimerfix(tv)
532 struct timeval *tv;
533 {
534
535 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
536 tv->tv_usec < 0 || tv->tv_usec >= 1000000)
537 return (EINVAL);
538 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
539 tv->tv_usec = tick;
540 return (0);
541 }
542
543 /*
544 * Decrement an interval timer by a specified number
545 * of microseconds, which must be less than a second,
546 * i.e. < 1000000. If the timer expires, then reload
547 * it. In this case, carry over (usec - old value) to
548 * reduce the value reloaded into the timer so that
549 * the timer does not drift. This routine assumes
550 * that it is called in a context where the timers
551 * on which it is operating cannot change in value.
552 */
553 int
554 itimerdecr(itp, usec)
555 register struct itimerval *itp;
556 int usec;
557 {
558
559 if (itp->it_value.tv_usec < usec) {
560 if (itp->it_value.tv_sec == 0) {
561 /* expired, and already in next interval */
562 usec -= itp->it_value.tv_usec;
563 goto expire;
564 }
565 itp->it_value.tv_usec += 1000000;
566 itp->it_value.tv_sec--;
567 }
568 itp->it_value.tv_usec -= usec;
569 usec = 0;
570 if (timerisset(&itp->it_value))
571 return (1);
572 /* expired, exactly at end of interval */
573 expire:
574 if (timerisset(&itp->it_interval)) {
575 itp->it_value = itp->it_interval;
576 itp->it_value.tv_usec -= usec;
577 if (itp->it_value.tv_usec < 0) {
578 itp->it_value.tv_usec += 1000000;
579 itp->it_value.tv_sec--;
580 }
581 } else
582 itp->it_value.tv_usec = 0; /* sec is already 0 */
583 return (0);
584 }
585