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