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