|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3: * 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: *
1.1.1.2 ! root 33: * from: @(#)kern_time.c 7.15 (Berkeley) 3/17/91
! 34: * kern_time.c,v 1.4 1993/07/13 22:13:28 cgd Exp
1.1 root 35: */
36:
37: #include "param.h"
1.1.1.2 ! root 38: #include "systm.h"
1.1 root 39: #include "resourcevar.h"
40: #include "kernel.h"
41: #include "proc.h"
42:
43: #include "machine/cpu.h"
44:
45: /*
46: * Time of day and interval timer support.
47: *
48: * These routines provide the kernel entry points to get and set
49: * the time-of-day and per-process interval timers. Subroutines
50: * here provide support for adding and subtracting timeval structures
51: * and decrementing interval timers, optionally reloading the interval
52: * timers when they expire.
53: */
54:
1.1.1.2 ! root 55: struct gettimeofday_args {
! 56: struct timeval *tp;
! 57: struct timezone *tzp;
! 58: };
! 59:
1.1 root 60: /* ARGSUSED */
1.1.1.2 ! root 61: int
1.1 root 62: gettimeofday(p, uap, retval)
63: struct proc *p;
1.1.1.2 ! root 64: register struct gettimeofday_args *uap;
1.1 root 65: int *retval;
66: {
67: struct timeval atv;
68: int error = 0;
69:
70: if (uap->tp) {
71: microtime(&atv);
72: if (error = copyout((caddr_t)&atv, (caddr_t)uap->tp,
73: sizeof (atv)))
74: return (error);
75: }
76: if (uap->tzp)
77: error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
78: sizeof (tz));
79: return (error);
80: }
81:
1.1.1.2 ! root 82: struct settimeofday_args {
! 83: struct timeval *tv;
! 84: struct timezone *tzp;
! 85: };
! 86:
1.1 root 87: /* ARGSUSED */
1.1.1.2 ! root 88: int
1.1 root 89: settimeofday(p, uap, retval)
90: struct proc *p;
1.1.1.2 ! root 91: struct settimeofday_args *uap;
1.1 root 92: int *retval;
93: {
94: struct timeval atv;
95: struct timezone atz;
96: int error, s;
97:
98: if (error = suser(p->p_ucred, &p->p_acflag))
99: return (error);
100: if (uap->tv) {
101: if (error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
102: sizeof (struct timeval)))
103: return (error);
104: /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
105: boottime.tv_sec += atv.tv_sec - time.tv_sec;
106: s = splhigh(); time = atv; splx(s);
107: resettodr();
108: }
109: if (uap->tzp && (error = copyin((caddr_t)uap->tzp, (caddr_t)&atz,
110: sizeof (atz))) == 0)
111: tz = atz;
112: return (error);
113: }
114:
115: extern int tickadj; /* "standard" clock skew, us./tick */
116: int tickdelta; /* current clock skew, us. per tick */
117: long timedelta; /* unapplied time correction, us. */
118: long bigadj = 1000000; /* use 10x skew above bigadj us. */
119:
1.1.1.2 ! root 120: struct adjtime_args {
! 121: struct timeval *delta;
! 122: struct timeval *olddelta;
! 123: };
! 124:
1.1 root 125: /* ARGSUSED */
1.1.1.2 ! root 126: int
1.1 root 127: adjtime(p, uap, retval)
128: struct proc *p;
1.1.1.2 ! root 129: register struct adjtime_args *uap;
1.1 root 130: int *retval;
131: {
132: struct timeval atv, oatv;
133: register long ndelta;
134: int s, error;
135:
136: if (error = suser(p->p_ucred, &p->p_acflag))
137: return (error);
138: if (error =
139: copyin((caddr_t)uap->delta, (caddr_t)&atv, sizeof (struct timeval)))
140: return (error);
141: ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
142: if (timedelta == 0)
143: if (ndelta > bigadj)
144: tickdelta = 10 * tickadj;
145: else
146: tickdelta = tickadj;
147: if (ndelta % tickdelta)
148: ndelta = ndelta / tickadj * tickadj;
149:
150: s = splclock();
151: if (uap->olddelta) {
152: oatv.tv_sec = timedelta / 1000000;
153: oatv.tv_usec = timedelta % 1000000;
154: }
155: timedelta = ndelta;
156: splx(s);
157:
158: if (uap->olddelta)
159: (void) copyout((caddr_t)&oatv, (caddr_t)uap->olddelta,
160: sizeof (struct timeval));
161: return (0);
162: }
163:
164: /*
165: * Get value of an interval timer. The process virtual and
166: * profiling virtual time timers are kept in the p_stats area, since
167: * they can be swapped out. These are kept internally in the
168: * way they are specified externally: in time until they expire.
169: *
170: * The real time interval timer is kept in the process table slot
171: * for the process, and its value (it_value) is kept as an
172: * absolute time rather than as a delta, so that it is easy to keep
173: * periodic real-time signals from drifting.
174: *
175: * Virtual time timers are processed in the hardclock() routine of
176: * kern_clock.c. The real time timer is processed by a timeout
177: * routine, called from the softclock() routine. Since a callout
178: * may be delayed in real time due to interrupt processing in the system,
179: * it is possible for the real time timeout routine (realitexpire, given below),
180: * to be delayed in real time past when it is supposed to occur. It
181: * does not suffice, therefore, to reload the real timer .it_value from the
182: * real time timers .it_interval. Rather, we compute the next time in
183: * absolute time the timer should go off.
184: */
1.1.1.2 ! root 185:
! 186: struct getitimer_args {
! 187: u_int which;
! 188: struct itimerval *itv;
! 189: };
! 190:
1.1 root 191: /* ARGSUSED */
1.1.1.2 ! root 192: int
1.1 root 193: getitimer(p, uap, retval)
194: struct proc *p;
1.1.1.2 ! root 195: register struct getitimer_args *uap;
1.1 root 196: int *retval;
197: {
198: struct itimerval aitv;
199: int s;
200:
201: if (uap->which > ITIMER_PROF)
202: return (EINVAL);
203: s = splclock();
204: if (uap->which == ITIMER_REAL) {
205: /*
206: * Convert from absoulte to relative time in .it_value
207: * part of real time timer. If time for real time timer
208: * has passed return 0, else return difference between
209: * current time and time for the timer to go off.
210: */
211: aitv = p->p_realtimer;
212: if (timerisset(&aitv.it_value))
213: if (timercmp(&aitv.it_value, &time, <))
214: timerclear(&aitv.it_value);
215: else
216: timevalsub(&aitv.it_value, &time);
217: } else
218: aitv = p->p_stats->p_timer[uap->which];
219: splx(s);
220: return (copyout((caddr_t)&aitv, (caddr_t)uap->itv,
221: sizeof (struct itimerval)));
222: }
223:
1.1.1.2 ! root 224: struct setitimer_args {
! 225: u_int which;
! 226: struct itimerval *itv, *oitv;
! 227: };
! 228:
1.1 root 229: /* ARGSUSED */
1.1.1.2 ! root 230: int
1.1 root 231: setitimer(p, uap, retval)
232: struct proc *p;
1.1.1.2 ! root 233: register struct setitimer_args *uap;
1.1 root 234: int *retval;
235: {
236: struct itimerval aitv;
237: register struct itimerval *itvp;
238: int s, error;
239:
240: if (uap->which > ITIMER_PROF)
241: return (EINVAL);
242: itvp = uap->itv;
243: if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
244: sizeof(struct itimerval))))
245: return (error);
246: if ((uap->itv = uap->oitv) && (error = getitimer(p, uap, retval)))
247: return (error);
248: if (itvp == 0)
249: return (0);
250: if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
251: return (EINVAL);
252: s = splclock();
253: if (uap->which == ITIMER_REAL) {
1.1.1.2 ! root 254: untimeout((timeout_t)realitexpire, (caddr_t)p);
1.1 root 255: if (timerisset(&aitv.it_value)) {
256: timevaladd(&aitv.it_value, &time);
1.1.1.2 ! root 257: timeout((timeout_t)realitexpire, (caddr_t)p, hzto(&aitv.it_value));
1.1 root 258: }
259: p->p_realtimer = aitv;
260: } else
261: p->p_stats->p_timer[uap->which] = aitv;
262: splx(s);
263: return (0);
264: }
265:
266: /*
267: * Real interval timer expired:
268: * send process whose timer expired an alarm signal.
269: * If time is not set up to reload, then just return.
270: * Else compute next time timer should go off which is > current time.
271: * This is where delay in processing this timeout causes multiple
272: * SIGALRM calls to be compressed into one.
273: */
1.1.1.2 ! root 274: void
1.1 root 275: realitexpire(p)
276: register struct proc *p;
277: {
278: int s;
279:
280: psignal(p, SIGALRM);
281: if (!timerisset(&p->p_realtimer.it_interval)) {
282: timerclear(&p->p_realtimer.it_value);
283: return;
284: }
285: for (;;) {
286: s = splclock();
287: timevaladd(&p->p_realtimer.it_value,
288: &p->p_realtimer.it_interval);
289: if (timercmp(&p->p_realtimer.it_value, &time, >)) {
1.1.1.2 ! root 290: timeout((timeout_t)realitexpire, (caddr_t)p,
1.1 root 291: hzto(&p->p_realtimer.it_value));
292: splx(s);
293: return;
294: }
295: splx(s);
296: }
297: }
298:
299: /*
300: * Check that a proposed value to load into the .it_value or
301: * .it_interval part of an interval timer is acceptable, and
302: * fix it to have at least minimal value (i.e. if it is less
303: * than the resolution of the clock, round it up.)
304: */
1.1.1.2 ! root 305: int
1.1 root 306: itimerfix(tv)
307: struct timeval *tv;
308: {
309:
310: if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
311: tv->tv_usec < 0 || tv->tv_usec >= 1000000)
312: return (EINVAL);
313: if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
314: tv->tv_usec = tick;
315: return (0);
316: }
317:
318: /*
319: * Decrement an interval timer by a specified number
320: * of microseconds, which must be less than a second,
321: * i.e. < 1000000. If the timer expires, then reload
322: * it. In this case, carry over (usec - old value) to
323: * reducint the value reloaded into the timer so that
324: * the timer does not drift. This routine assumes
325: * that it is called in a context where the timers
326: * on which it is operating cannot change in value.
327: */
1.1.1.2 ! root 328: int
1.1 root 329: itimerdecr(itp, usec)
330: register struct itimerval *itp;
331: int usec;
332: {
333:
334: if (itp->it_value.tv_usec < usec) {
335: if (itp->it_value.tv_sec == 0) {
336: /* expired, and already in next interval */
337: usec -= itp->it_value.tv_usec;
338: goto expire;
339: }
340: itp->it_value.tv_usec += 1000000;
341: itp->it_value.tv_sec--;
342: }
343: itp->it_value.tv_usec -= usec;
344: usec = 0;
345: if (timerisset(&itp->it_value))
346: return (1);
347: /* expired, exactly at end of interval */
348: expire:
349: if (timerisset(&itp->it_interval)) {
350: itp->it_value = itp->it_interval;
351: itp->it_value.tv_usec -= usec;
352: if (itp->it_value.tv_usec < 0) {
353: itp->it_value.tv_usec += 1000000;
354: itp->it_value.tv_sec--;
355: }
356: } else
357: itp->it_value.tv_usec = 0; /* sec is already 0 */
358: return (0);
359: }
360:
361: /*
362: * Add and subtract routines for timevals.
363: * N.B.: subtract routine doesn't deal with
364: * results which are before the beginning,
365: * it just gets very confused in this case.
366: * Caveat emptor.
367: */
1.1.1.2 ! root 368: void
1.1 root 369: timevaladd(t1, t2)
370: struct timeval *t1, *t2;
371: {
372:
373: t1->tv_sec += t2->tv_sec;
374: t1->tv_usec += t2->tv_usec;
375: timevalfix(t1);
376: }
377:
1.1.1.2 ! root 378: void
1.1 root 379: timevalsub(t1, t2)
380: struct timeval *t1, *t2;
381: {
382:
383: t1->tv_sec -= t2->tv_sec;
384: t1->tv_usec -= t2->tv_usec;
385: timevalfix(t1);
386: }
387:
1.1.1.2 ! root 388: void
1.1 root 389: timevalfix(t1)
390: struct timeval *t1;
391: {
392:
393: if (t1->tv_usec < 0) {
394: t1->tv_sec--;
395: t1->tv_usec += 1000000;
396: }
397: if (t1->tv_usec >= 1000000) {
398: t1->tv_sec++;
399: t1->tv_usec -= 1000000;
400: }
401: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.