1dcae39bdSmckusick /*
28f6f57faSbostic * Copyright (c) 1982, 1986, 1989, 1993
38f6f57faSbostic * The Regents of the University of California. All rights reserved.
4dcae39bdSmckusick *
5b383d302Sbostic * %sccs.include.redist.c%
6014695a9Smckusick *
7*7316b25aSmckusick * @(#)kern_time.c 8.4 (Berkeley) 05/26/95
8dcae39bdSmckusick */
9db51853bSsam
106e23d7a0Sbostic #include <sys/param.h>
116e23d7a0Sbostic #include <sys/resourcevar.h>
126e23d7a0Sbostic #include <sys/kernel.h>
136e23d7a0Sbostic #include <sys/systm.h>
146e23d7a0Sbostic #include <sys/proc.h>
156e23d7a0Sbostic #include <sys/vnode.h>
16ef678427Sroot
17ab04d79bScgd #include <sys/mount.h>
18ab04d79bScgd #include <sys/syscallargs.h>
19ab04d79bScgd
206e23d7a0Sbostic #include <machine/cpu.h>
2167a72975Skarels
2272762883Sroot /*
2372762883Sroot * Time of day and interval timer support.
2434eef8ebSroot *
2534eef8ebSroot * These routines provide the kernel entry points to get and set
2634eef8ebSroot * the time-of-day and per-process interval timers. Subroutines
2734eef8ebSroot * here provide support for adding and subtracting timeval structures
2834eef8ebSroot * and decrementing interval timers, optionally reloading the interval
2934eef8ebSroot * timers when they expire.
3072762883Sroot */
3172762883Sroot
32d1ec48c2Skarels /* ARGSUSED */
33ab04d79bScgd int
gettimeofday(p,uap,retval)34d1ec48c2Skarels gettimeofday(p, uap, retval)
35d1ec48c2Skarels struct proc *p;
36ab04d79bScgd register struct gettimeofday_args /* {
37ab04d79bScgd syscallarg(struct timeval *) tp;
38ab04d79bScgd syscallarg(struct timezone *) tzp;
39ab04d79bScgd } */ *uap;
40ab04d79bScgd register_t *retval;
41d1ec48c2Skarels {
42ef678427Sroot struct timeval atv;
43d1ec48c2Skarels int error = 0;
44ef678427Sroot
45ab04d79bScgd if (SCARG(uap, tp)) {
4670dbe469Skarels microtime(&atv);
47ab04d79bScgd if (error = copyout((caddr_t)&atv, (caddr_t)SCARG(uap, tp),
48d1ec48c2Skarels sizeof (atv)))
492c51c3e4Skarels return (error);
502da4521eSbostic }
51ab04d79bScgd if (SCARG(uap, tzp))
52ab04d79bScgd error = copyout((caddr_t)&tz, (caddr_t)SCARG(uap, tzp),
532da4521eSbostic sizeof (tz));
542c51c3e4Skarels return (error);
55ef678427Sroot }
56ef678427Sroot
57187e1fb7Sbostic /* ARGSUSED */
58ab04d79bScgd int
settimeofday(p,uap,retval)59d1ec48c2Skarels settimeofday(p, uap, retval)
60d1ec48c2Skarels struct proc *p;
61ab04d79bScgd struct settimeofday_args /* {
62ab04d79bScgd syscallarg(struct timeval *) tv;
63ab04d79bScgd syscallarg(struct timezone *) tzp;
64ab04d79bScgd } */ *uap;
65ab04d79bScgd register_t *retval;
66d1ec48c2Skarels {
67e4223d7eStorek struct timeval atv, delta;
68ef678427Sroot struct timezone atz;
69d1ec48c2Skarels int error, s;
70ef678427Sroot
710b0833e3Skarels if (error = suser(p->p_ucred, &p->p_acflag))
722c51c3e4Skarels return (error);
73e4223d7eStorek /* Verify all parameters before changing time. */
74ab04d79bScgd if (SCARG(uap, tv) && (error = copyin((caddr_t)SCARG(uap, tv),
75ab04d79bScgd (caddr_t)&atv, sizeof(atv))))
762c51c3e4Skarels return (error);
77ab04d79bScgd if (SCARG(uap, tzp) && (error = copyin((caddr_t)SCARG(uap, tzp),
78ab04d79bScgd (caddr_t)&atz, sizeof(atz))))
79e4223d7eStorek return (error);
80ab04d79bScgd if (SCARG(uap, tv)) {
81*7316b25aSmckusick /*
82*7316b25aSmckusick * If the system is secure, we do not allow the time to be
83*7316b25aSmckusick * set to an earlier value (it may be slowed using adjtime,
84*7316b25aSmckusick * but not set back). This feature prevent interlopers from
85*7316b25aSmckusick * setting arbitrary time stamps on files.
86*7316b25aSmckusick */
87*7316b25aSmckusick if (securelevel > 0 && timercmp(&atv, &time, <))
88*7316b25aSmckusick return (EPERM);
89014695a9Smckusick /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
90e4223d7eStorek s = splclock();
91e4223d7eStorek /* nb. delta.tv_usec may be < 0, but this is OK here */
92e4223d7eStorek delta.tv_sec = atv.tv_sec - time.tv_sec;
93e4223d7eStorek delta.tv_usec = atv.tv_usec - time.tv_usec;
94e4223d7eStorek time = atv;
95e4223d7eStorek (void) splsoftclock();
96e4223d7eStorek timevaladd(&boottime, &delta);
97e4223d7eStorek timevalfix(&boottime);
98e4223d7eStorek timevaladd(&runtime, &delta);
99e4223d7eStorek timevalfix(&runtime);
10096c192e5Smckusick # ifdef NFS
10196c192e5Smckusick lease_updatetime(delta.tv_sec);
10296c192e5Smckusick # endif
103e4223d7eStorek splx(s);
104014695a9Smckusick resettodr();
1052da4521eSbostic }
106ab04d79bScgd if (SCARG(uap, tzp))
1070228495eSsam tz = atz;
108e4223d7eStorek return (0);
109ef678427Sroot }
11072762883Sroot
111a690062aSkarels extern int tickadj; /* "standard" clock skew, us./tick */
112a690062aSkarels int tickdelta; /* current clock skew, us. per tick */
113a690062aSkarels long timedelta; /* unapplied time correction, us. */
114a690062aSkarels long bigadj = 1000000; /* use 10x skew above bigadj us. */
1155d3ec6cbSkarels
116d1ec48c2Skarels /* ARGSUSED */
117ab04d79bScgd int
adjtime(p,uap,retval)118d1ec48c2Skarels adjtime(p, uap, retval)
119d1ec48c2Skarels struct proc *p;
120ab04d79bScgd register struct adjtime_args /* {
121ab04d79bScgd syscallarg(struct timeval *) delta;
122ab04d79bScgd syscallarg(struct timeval *) olddelta;
123ab04d79bScgd } */ *uap;
124ab04d79bScgd register_t *retval;
125d1ec48c2Skarels {
126cbd24f66Storek struct timeval atv;
127cbd24f66Storek register long ndelta, ntickdelta, odelta;
128d1ec48c2Skarels int s, error;
1295d3ec6cbSkarels
1300b0833e3Skarels if (error = suser(p->p_ucred, &p->p_acflag))
1312c51c3e4Skarels return (error);
132ab04d79bScgd if (error = copyin((caddr_t)SCARG(uap, delta), (caddr_t)&atv,
133ab04d79bScgd sizeof(struct timeval)))
1342c51c3e4Skarels return (error);
135a690062aSkarels
136cbd24f66Storek /*
137cbd24f66Storek * Compute the total correction and the rate at which to apply it.
138cbd24f66Storek * Round the adjustment down to a whole multiple of the per-tick
139cbd24f66Storek * delta, so that after some number of incremental changes in
140cbd24f66Storek * hardclock(), tickdelta will become zero, lest the correction
141cbd24f66Storek * overshoot and start taking us away from the desired final time.
142cbd24f66Storek */
143cbd24f66Storek ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
144cbd24f66Storek if (ndelta > bigadj)
145cbd24f66Storek ntickdelta = 10 * tickadj;
146cbd24f66Storek else
147cbd24f66Storek ntickdelta = tickadj;
148cbd24f66Storek if (ndelta % ntickdelta)
149cbd24f66Storek ndelta = ndelta / ntickdelta * ntickdelta;
150cbd24f66Storek
151cbd24f66Storek /*
152cbd24f66Storek * To make hardclock()'s job easier, make the per-tick delta negative
153cbd24f66Storek * if we want time to run slower; then hardclock can simply compute
154cbd24f66Storek * tick + tickdelta, and subtract tickdelta from timedelta.
155cbd24f66Storek */
156cbd24f66Storek if (ndelta < 0)
157cbd24f66Storek ntickdelta = -ntickdelta;
158e782b972Skarels s = splclock();
159cbd24f66Storek odelta = timedelta;
160a690062aSkarels timedelta = ndelta;
161cbd24f66Storek tickdelta = ntickdelta;
162a690062aSkarels splx(s);
163a690062aSkarels
164ab04d79bScgd if (SCARG(uap, olddelta)) {
165cbd24f66Storek atv.tv_sec = odelta / 1000000;
166cbd24f66Storek atv.tv_usec = odelta % 1000000;
167ab04d79bScgd (void) copyout((caddr_t)&atv, (caddr_t)SCARG(uap, olddelta),
1685d3ec6cbSkarels sizeof(struct timeval));
169cbd24f66Storek }
1702c51c3e4Skarels return (0);
1715d3ec6cbSkarels }
1725d3ec6cbSkarels
17334eef8ebSroot /*
17434eef8ebSroot * Get value of an interval timer. The process virtual and
1750b0833e3Skarels * profiling virtual time timers are kept in the p_stats area, since
17634eef8ebSroot * they can be swapped out. These are kept internally in the
17734eef8ebSroot * way they are specified externally: in time until they expire.
17834eef8ebSroot *
17934eef8ebSroot * The real time interval timer is kept in the process table slot
18034eef8ebSroot * for the process, and its value (it_value) is kept as an
18134eef8ebSroot * absolute time rather than as a delta, so that it is easy to keep
18234eef8ebSroot * periodic real-time signals from drifting.
18334eef8ebSroot *
18434eef8ebSroot * Virtual time timers are processed in the hardclock() routine of
18534eef8ebSroot * kern_clock.c. The real time timer is processed by a timeout
18634eef8ebSroot * routine, called from the softclock() routine. Since a callout
18734eef8ebSroot * may be delayed in real time due to interrupt processing in the system,
18834eef8ebSroot * it is possible for the real time timeout routine (realitexpire, given below),
18934eef8ebSroot * to be delayed in real time past when it is supposed to occur. It
19034eef8ebSroot * does not suffice, therefore, to reload the real timer .it_value from the
19134eef8ebSroot * real time timers .it_interval. Rather, we compute the next time in
19234eef8ebSroot * absolute time the timer should go off.
19334eef8ebSroot */
194d1ec48c2Skarels /* ARGSUSED */
195ab04d79bScgd int
getitimer(p,uap,retval)196d1ec48c2Skarels getitimer(p, uap, retval)
197d1ec48c2Skarels struct proc *p;
198ab04d79bScgd register struct getitimer_args /* {
199ab04d79bScgd syscallarg(u_int) which;
200ab04d79bScgd syscallarg(struct itimerval *) itv;
201ab04d79bScgd } */ *uap;
202ab04d79bScgd register_t *retval;
203d1ec48c2Skarels {
2040ed3b3c8Sroot struct itimerval aitv;
205ef678427Sroot int s;
206ef678427Sroot
207ab04d79bScgd if (SCARG(uap, which) > ITIMER_PROF)
2082c51c3e4Skarels return (EINVAL);
20970dbe469Skarels s = splclock();
210ab04d79bScgd if (SCARG(uap, which) == ITIMER_REAL) {
21134eef8ebSroot /*
212ab04d79bScgd * Convert from absolute to relative time in .it_value
21334eef8ebSroot * part of real time timer. If time for real time timer
21434eef8ebSroot * has passed return 0, else return difference between
21534eef8ebSroot * current time and time for the timer to go off.
21634eef8ebSroot */
217d1ec48c2Skarels aitv = p->p_realtimer;
2180ed3b3c8Sroot if (timerisset(&aitv.it_value))
2190ed3b3c8Sroot if (timercmp(&aitv.it_value, &time, <))
2200ed3b3c8Sroot timerclear(&aitv.it_value);
2210ed3b3c8Sroot else
222e4223d7eStorek timevalsub(&aitv.it_value,
223e4223d7eStorek (struct timeval *)&time);
2240ed3b3c8Sroot } else
225ab04d79bScgd aitv = p->p_stats->p_timer[SCARG(uap, which)];
2260ed3b3c8Sroot splx(s);
227ab04d79bScgd return (copyout((caddr_t)&aitv, (caddr_t)SCARG(uap, itv),
228d1ec48c2Skarels sizeof (struct itimerval)));
229ef678427Sroot }
230ef678427Sroot
231d1ec48c2Skarels /* ARGSUSED */
232ab04d79bScgd int
setitimer(p,uap,retval)233d1ec48c2Skarels setitimer(p, uap, retval)
234d1ec48c2Skarels struct proc *p;
235ab04d79bScgd register struct setitimer_args /* {
236ab04d79bScgd syscallarg(u_int) which;
237ab04d79bScgd syscallarg(struct itimerval *) itv;
238ab04d79bScgd syscallarg(struct itimerval *) oitv;
239ab04d79bScgd } */ *uap;
240ab04d79bScgd register_t *retval;
241d1ec48c2Skarels {
2423468c2f1Smckusick struct itimerval aitv;
2433468c2f1Smckusick register struct itimerval *itvp;
244d1ec48c2Skarels int s, error;
245ef678427Sroot
246ab04d79bScgd if (SCARG(uap, which) > ITIMER_PROF)
2472c51c3e4Skarels return (EINVAL);
248ab04d79bScgd itvp = SCARG(uap, itv);
249d1ec48c2Skarels if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
2503468c2f1Smckusick sizeof(struct itimerval))))
2512c51c3e4Skarels return (error);
252ab04d79bScgd if ((SCARG(uap, itv) = SCARG(uap, oitv)) &&
253ab04d79bScgd (error = getitimer(p, uap, retval)))
2542c51c3e4Skarels return (error);
2553468c2f1Smckusick if (itvp == 0)
256d1ec48c2Skarels return (0);
257d1ec48c2Skarels if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
2582c51c3e4Skarels return (EINVAL);
25970dbe469Skarels s = splclock();
260ab04d79bScgd if (SCARG(uap, which) == ITIMER_REAL) {
261a11faa3dSroot untimeout(realitexpire, (caddr_t)p);
2620ed3b3c8Sroot if (timerisset(&aitv.it_value)) {
263e4223d7eStorek timevaladd(&aitv.it_value, (struct timeval *)&time);
264a11faa3dSroot timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value));
2650ed3b3c8Sroot }
2660ed3b3c8Sroot p->p_realtimer = aitv;
2670ed3b3c8Sroot } else
268ab04d79bScgd p->p_stats->p_timer[SCARG(uap, which)] = aitv;
269ef678427Sroot splx(s);
2702c51c3e4Skarels return (0);
271ef678427Sroot }
272ef678427Sroot
27334eef8ebSroot /*
27434eef8ebSroot * Real interval timer expired:
27534eef8ebSroot * send process whose timer expired an alarm signal.
27634eef8ebSroot * If time is not set up to reload, then just return.
27734eef8ebSroot * Else compute next time timer should go off which is > current time.
27834eef8ebSroot * This is where delay in processing this timeout causes multiple
27934eef8ebSroot * SIGALRM calls to be compressed into one.
28034eef8ebSroot */
281e4223d7eStorek void
realitexpire(arg)282e4223d7eStorek realitexpire(arg)
283e4223d7eStorek void *arg;
2840ed3b3c8Sroot {
285e4223d7eStorek register struct proc *p;
2860ed3b3c8Sroot int s;
2870ed3b3c8Sroot
288e4223d7eStorek p = (struct proc *)arg;
2890ed3b3c8Sroot psignal(p, SIGALRM);
2900ed3b3c8Sroot if (!timerisset(&p->p_realtimer.it_interval)) {
2910ed3b3c8Sroot timerclear(&p->p_realtimer.it_value);
2920ed3b3c8Sroot return;
2930ed3b3c8Sroot }
2940ed3b3c8Sroot for (;;) {
29570dbe469Skarels s = splclock();
2960ed3b3c8Sroot timevaladd(&p->p_realtimer.it_value,
2970ed3b3c8Sroot &p->p_realtimer.it_interval);
2980ed3b3c8Sroot if (timercmp(&p->p_realtimer.it_value, &time, >)) {
299a11faa3dSroot timeout(realitexpire, (caddr_t)p,
300a11faa3dSroot hzto(&p->p_realtimer.it_value));
3010ed3b3c8Sroot splx(s);
3020ed3b3c8Sroot return;
3030ed3b3c8Sroot }
3040ed3b3c8Sroot splx(s);
3050ed3b3c8Sroot }
3060ed3b3c8Sroot }
3070ed3b3c8Sroot
30834eef8ebSroot /*
30934eef8ebSroot * Check that a proposed value to load into the .it_value or
31034eef8ebSroot * .it_interval part of an interval timer is acceptable, and
31134eef8ebSroot * fix it to have at least minimal value (i.e. if it is less
31234eef8ebSroot * than the resolution of the clock, round it up.)
31334eef8ebSroot */
314ab04d79bScgd int
itimerfix(tv)31572762883Sroot itimerfix(tv)
31672762883Sroot struct timeval *tv;
31772762883Sroot {
31872762883Sroot
3190ed3b3c8Sroot if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
3200ed3b3c8Sroot tv->tv_usec < 0 || tv->tv_usec >= 1000000)
32172762883Sroot return (EINVAL);
32242312cf9Ssam if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
32372762883Sroot tv->tv_usec = tick;
32472762883Sroot return (0);
32572762883Sroot }
32672762883Sroot
32734eef8ebSroot /*
32834eef8ebSroot * Decrement an interval timer by a specified number
32934eef8ebSroot * of microseconds, which must be less than a second,
33034eef8ebSroot * i.e. < 1000000. If the timer expires, then reload
33134eef8ebSroot * it. In this case, carry over (usec - old value) to
332e4223d7eStorek * reduce the value reloaded into the timer so that
33334eef8ebSroot * the timer does not drift. This routine assumes
33434eef8ebSroot * that it is called in a context where the timers
33534eef8ebSroot * on which it is operating cannot change in value.
33634eef8ebSroot */
337ab04d79bScgd int
itimerdecr(itp,usec)338ef678427Sroot itimerdecr(itp, usec)
339ef678427Sroot register struct itimerval *itp;
340ef678427Sroot int usec;
341ef678427Sroot {
342ef678427Sroot
34372762883Sroot if (itp->it_value.tv_usec < usec) {
34472762883Sroot if (itp->it_value.tv_sec == 0) {
34534eef8ebSroot /* expired, and already in next interval */
34672762883Sroot usec -= itp->it_value.tv_usec;
347ef678427Sroot goto expire;
348ef678427Sroot }
34972762883Sroot itp->it_value.tv_usec += 1000000;
35072762883Sroot itp->it_value.tv_sec--;
35172762883Sroot }
35272762883Sroot itp->it_value.tv_usec -= usec;
35372762883Sroot usec = 0;
35472762883Sroot if (timerisset(&itp->it_value))
355ef678427Sroot return (1);
35634eef8ebSroot /* expired, exactly at end of interval */
357ef678427Sroot expire:
35872762883Sroot if (timerisset(&itp->it_interval)) {
35972762883Sroot itp->it_value = itp->it_interval;
36072762883Sroot itp->it_value.tv_usec -= usec;
36172762883Sroot if (itp->it_value.tv_usec < 0) {
36272762883Sroot itp->it_value.tv_usec += 1000000;
36372762883Sroot itp->it_value.tv_sec--;
36472762883Sroot }
36572762883Sroot } else
36634eef8ebSroot itp->it_value.tv_usec = 0; /* sec is already 0 */
367ef678427Sroot return (0);
368ef678427Sroot }
369ef678427Sroot
37034eef8ebSroot /*
37134eef8ebSroot * Add and subtract routines for timevals.
37234eef8ebSroot * N.B.: subtract routine doesn't deal with
37334eef8ebSroot * results which are before the beginning,
37434eef8ebSroot * it just gets very confused in this case.
37534eef8ebSroot * Caveat emptor.
37634eef8ebSroot */
37734eef8ebSroot timevaladd(t1, t2)
37834eef8ebSroot struct timeval *t1, *t2;
37934eef8ebSroot {
38034eef8ebSroot
38134eef8ebSroot t1->tv_sec += t2->tv_sec;
38234eef8ebSroot t1->tv_usec += t2->tv_usec;
38334eef8ebSroot timevalfix(t1);
38434eef8ebSroot }
38534eef8ebSroot
38634eef8ebSroot timevalsub(t1, t2)
38734eef8ebSroot struct timeval *t1, *t2;
38834eef8ebSroot {
38934eef8ebSroot
39034eef8ebSroot t1->tv_sec -= t2->tv_sec;
39134eef8ebSroot t1->tv_usec -= t2->tv_usec;
39234eef8ebSroot timevalfix(t1);
39334eef8ebSroot }
39434eef8ebSroot
39534eef8ebSroot timevalfix(t1)
39634eef8ebSroot struct timeval *t1;
39734eef8ebSroot {
39834eef8ebSroot
39934eef8ebSroot if (t1->tv_usec < 0) {
40034eef8ebSroot t1->tv_sec--;
40134eef8ebSroot t1->tv_usec += 1000000;
40234eef8ebSroot }
40334eef8ebSroot if (t1->tv_usec >= 1000000) {
40434eef8ebSroot t1->tv_sec++;
40534eef8ebSroot t1->tv_usec -= 1000000;
40634eef8ebSroot }
40734eef8ebSroot }
408