Annotation of src/sys/kern/kern_time.c, Revision 1.33
1.33 ! fvdl 1: /* $NetBSD: kern_time.c,v 1.32 1998/02/20 07:22:14 mycroft Exp $ */
1.9 cgd 2:
1.1 cgd 3: /*
1.8 cgd 4: * Copyright (c) 1982, 1986, 1989, 1993
5: * The Regents of the University of California. All rights reserved.
1.1 cgd 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: *
1.33 ! fvdl 35: * @(#)kern_time.c 8.4 (Berkeley) 5/26/95
1.1 cgd 36: */
1.31 thorpej 37:
38: #include "fs_nfs.h"
1.1 cgd 39:
1.5 mycroft 40: #include <sys/param.h>
41: #include <sys/resourcevar.h>
42: #include <sys/kernel.h>
1.8 cgd 43: #include <sys/systm.h>
1.5 mycroft 44: #include <sys/proc.h>
1.8 cgd 45: #include <sys/vnode.h>
1.17 christos 46: #include <sys/signalvar.h>
1.25 perry 47: #include <sys/syslog.h>
1.1 cgd 48:
1.11 cgd 49: #include <sys/mount.h>
50: #include <sys/syscallargs.h>
1.19 christos 51:
1.26 thorpej 52: #if defined(NFS) || defined(NFSSERVER)
1.20 fvdl 53: #include <nfs/rpcv2.h>
54: #include <nfs/nfsproto.h>
1.19 christos 55: #include <nfs/nfs_var.h>
56: #endif
1.17 christos 57:
1.5 mycroft 58: #include <machine/cpu.h>
1.1 cgd 59:
1.29 tls 60: static int settime __P((struct timeval *));
1.23 cgd 61:
62: /*
1.1 cgd 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:
1.22 jtc 72: /* This function is used by clock_settime and settimeofday */
1.29 tls 73: static int
1.22 jtc 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);
1.29 tls 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
1.22 jtc 89: time = *tv;
90: (void) splsoftclock();
91: timeradd(&boottime, &delta, &boottime);
92: timeradd(&runtime, &delta, &runtime);
1.26 thorpej 93: # if defined(NFS) || defined(NFSSERVER)
1.22 jtc 94: nqnfs_lease_updatetime(delta.tv_sec);
95: # endif
96: splx(s);
97: resettodr();
1.29 tls 98: return (0);
1.22 jtc 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;
1.23 cgd 110: syscallarg(struct timespec *) tp;
111: } */ *uap = v;
1.22 jtc 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:
1.24 cgd 123: return copyout(&ats, SCARG(uap, tp), sizeof(ats));
1.22 jtc 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;
1.23 cgd 135: syscallarg(const struct timespec *) tp;
136: } */ *uap = v;
1.22 jtc 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:
1.24 cgd 149: if ((error = copyin(SCARG(uap, tp), &ats, sizeof(ats))) != 0)
1.23 cgd 150: return (error);
1.22 jtc 151:
152: TIMESPEC_TO_TIMEVAL(&atv,&ats);
1.29 tls 153: if ((error = settime(&atv)))
154: return (error);
1.22 jtc 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;
1.23 cgd 167: syscallarg(struct timespec *) tp;
168: } */ *uap = v;
1.22 jtc 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:
1.24 cgd 181: error = copyout(&ts, SCARG(uap, tp), sizeof (ts));
1.22 jtc 182: }
183:
184: return error;
185: }
186:
1.27 jtc 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)) {
1.28 jtc 230: int error;
231:
1.27 jtc 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),
1.28 jtc 242: sizeof(rmt));
243: if (error)
244: return (error);
1.27 jtc 245: }
246:
247: return error;
248: }
1.22 jtc 249:
1.1 cgd 250: /* ARGSUSED */
1.3 andrew 251: int
1.16 mycroft 252: sys_gettimeofday(p, v, retval)
1.1 cgd 253: struct proc *p;
1.15 thorpej 254: void *v;
255: register_t *retval;
256: {
1.16 mycroft 257: register struct sys_gettimeofday_args /* {
1.11 cgd 258: syscallarg(struct timeval *) tp;
259: syscallarg(struct timezone *) tzp;
1.15 thorpej 260: } */ *uap = v;
1.1 cgd 261: struct timeval atv;
262: int error = 0;
1.25 perry 263: struct timezone tzfake;
1.1 cgd 264:
1.11 cgd 265: if (SCARG(uap, tp)) {
1.1 cgd 266: microtime(&atv);
1.24 cgd 267: error = copyout(&atv, SCARG(uap, tp), sizeof (atv));
1.17 christos 268: if (error)
1.1 cgd 269: return (error);
270: }
1.25 perry 271: if (SCARG(uap, tzp)) {
272: /*
1.32 mycroft 273: * NetBSD has no kernel notion of time zone, so we just
1.25 perry 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: }
1.1 cgd 280: return (error);
281: }
282:
283: /* ARGSUSED */
1.3 andrew 284: int
1.16 mycroft 285: sys_settimeofday(p, v, retval)
1.1 cgd 286: struct proc *p;
1.15 thorpej 287: void *v;
288: register_t *retval;
289: {
1.16 mycroft 290: struct sys_settimeofday_args /* {
1.24 cgd 291: syscallarg(const struct timeval *) tv;
292: syscallarg(const struct timezone *) tzp;
1.15 thorpej 293: } */ *uap = v;
1.22 jtc 294: struct timeval atv;
1.1 cgd 295: struct timezone atz;
1.22 jtc 296: int error;
1.1 cgd 297:
1.17 christos 298: if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.1 cgd 299: return (error);
1.8 cgd 300: /* Verify all parameters before changing time. */
1.24 cgd 301: if (SCARG(uap, tv) && (error = copyin(SCARG(uap, tv),
302: &atv, sizeof(atv))))
1.8 cgd 303: return (error);
1.25 perry 304: /* XXX since we don't use tz, probably no point in doing copyin. */
1.24 cgd 305: if (SCARG(uap, tzp) && (error = copyin(SCARG(uap, tzp),
306: &atz, sizeof(atz))))
1.8 cgd 307: return (error);
1.22 jtc 308: if (SCARG(uap, tv))
1.29 tls 309: if ((error = settime(&atv)))
310: return (error);
1.25 perry 311: /*
1.32 mycroft 312: * NetBSD has no kernel notion of time zone, and only an
1.25 perry 313: * obsolete program would try to set it, so we log a warning.
314: */
1.11 cgd 315: if (SCARG(uap, tzp))
1.25 perry 316: log(LOG_WARNING, "pid %d attempted to set the "
1.32 mycroft 317: "(obsolete) kernel time zone\n", p->p_pid);
1.8 cgd 318: return (0);
1.1 cgd 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 */
1.3 andrew 326: int
1.16 mycroft 327: sys_adjtime(p, v, retval)
1.1 cgd 328: struct proc *p;
1.15 thorpej 329: void *v;
330: register_t *retval;
331: {
1.16 mycroft 332: register struct sys_adjtime_args /* {
1.24 cgd 333: syscallarg(const struct timeval *) delta;
1.11 cgd 334: syscallarg(struct timeval *) olddelta;
1.15 thorpej 335: } */ *uap = v;
1.8 cgd 336: struct timeval atv;
337: register long ndelta, ntickdelta, odelta;
1.1 cgd 338: int s, error;
339:
1.17 christos 340: if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.1 cgd 341: return (error);
1.17 christos 342:
1.24 cgd 343: error = copyin(SCARG(uap, delta), &atv, sizeof(struct timeval));
1.17 christos 344: if (error)
1.1 cgd 345: return (error);
1.8 cgd 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: */
1.1 cgd 354: ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
1.8 cgd 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;
1.1 cgd 369: s = splclock();
1.8 cgd 370: odelta = timedelta;
1.1 cgd 371: timedelta = ndelta;
1.8 cgd 372: tickdelta = ntickdelta;
1.1 cgd 373: splx(s);
374:
1.11 cgd 375: if (SCARG(uap, olddelta)) {
1.8 cgd 376: atv.tv_sec = odelta / 1000000;
377: atv.tv_usec = odelta % 1000000;
1.24 cgd 378: (void) copyout(&atv, SCARG(uap, olddelta),
1.8 cgd 379: sizeof(struct timeval));
380: }
1.1 cgd 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 */
1.3 andrew 406: int
1.16 mycroft 407: sys_getitimer(p, v, retval)
1.1 cgd 408: struct proc *p;
1.15 thorpej 409: void *v;
410: register_t *retval;
411: {
1.16 mycroft 412: register struct sys_getitimer_args /* {
1.30 mycroft 413: syscallarg(int) which;
1.11 cgd 414: syscallarg(struct itimerval *) itv;
1.15 thorpej 415: } */ *uap = v;
1.30 mycroft 416: int which = SCARG(uap, which);
1.1 cgd 417: struct itimerval aitv;
418: int s;
419:
1.30 mycroft 420: if ((u_int)which > ITIMER_PROF)
1.1 cgd 421: return (EINVAL);
422: s = splclock();
1.30 mycroft 423: if (which == ITIMER_REAL) {
1.1 cgd 424: /*
1.12 mycroft 425: * Convert from absolute to relative time in .it_value
1.1 cgd 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
1.14 mycroft 435: timersub(&aitv.it_value, &time, &aitv.it_value);
1.1 cgd 436: } else
1.30 mycroft 437: aitv = p->p_stats->p_timer[which];
1.1 cgd 438: splx(s);
1.24 cgd 439: return (copyout(&aitv, SCARG(uap, itv), sizeof (struct itimerval)));
1.1 cgd 440: }
441:
442: /* ARGSUSED */
1.3 andrew 443: int
1.16 mycroft 444: sys_setitimer(p, v, retval)
1.1 cgd 445: struct proc *p;
1.17 christos 446: register void *v;
1.15 thorpej 447: register_t *retval;
448: {
1.16 mycroft 449: register struct sys_setitimer_args /* {
1.30 mycroft 450: syscallarg(int) which;
1.24 cgd 451: syscallarg(const struct itimerval *) itv;
1.11 cgd 452: syscallarg(struct itimerval *) oitv;
1.15 thorpej 453: } */ *uap = v;
1.30 mycroft 454: int which = SCARG(uap, which);
1.21 cgd 455: struct sys_getitimer_args getargs;
1.1 cgd 456: struct itimerval aitv;
1.24 cgd 457: register const struct itimerval *itvp;
1.1 cgd 458: int s, error;
459:
1.30 mycroft 460: if ((u_int)which > ITIMER_PROF)
1.1 cgd 461: return (EINVAL);
1.11 cgd 462: itvp = SCARG(uap, itv);
1.24 cgd 463: if (itvp && (error = copyin(itvp, &aitv, sizeof(struct itimerval))))
1.1 cgd 464: return (error);
1.21 cgd 465: if (SCARG(uap, oitv) != NULL) {
1.30 mycroft 466: SCARG(&getargs, which) = which;
1.21 cgd 467: SCARG(&getargs, itv) = SCARG(uap, oitv);
1.23 cgd 468: if ((error = sys_getitimer(p, &getargs, retval)) != 0)
1.21 cgd 469: return (error);
470: }
1.1 cgd 471: if (itvp == 0)
472: return (0);
473: if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
474: return (EINVAL);
475: s = splclock();
1.30 mycroft 476: if (which == ITIMER_REAL) {
1.7 mycroft 477: untimeout(realitexpire, p);
1.1 cgd 478: if (timerisset(&aitv.it_value)) {
1.14 mycroft 479: timeradd(&aitv.it_value, &time, &aitv.it_value);
1.7 mycroft 480: timeout(realitexpire, p, hzto(&aitv.it_value));
1.1 cgd 481: }
482: p->p_realtimer = aitv;
483: } else
1.30 mycroft 484: p->p_stats->p_timer[which] = aitv;
1.1 cgd 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: */
1.3 andrew 497: void
1.6 cgd 498: realitexpire(arg)
499: void *arg;
500: {
1.1 cgd 501: register struct proc *p;
502: int s;
503:
1.6 cgd 504: p = (struct proc *)arg;
1.1 cgd 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();
1.14 mycroft 512: timeradd(&p->p_realtimer.it_value,
513: &p->p_realtimer.it_interval, &p->p_realtimer.it_value);
1.1 cgd 514: if (timercmp(&p->p_realtimer.it_value, &time, >)) {
1.7 mycroft 515: timeout(realitexpire, p,
1.1 cgd 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: */
1.3 andrew 530: int
1.1 cgd 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
1.8 cgd 548: * reduce the value reloaded into the timer so that
1.1 cgd 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: */
1.3 andrew 553: int
1.1 cgd 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: }
CVSweb <webmaster@jp.NetBSD.org>