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