1: /*
2: * Copyright (c) 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)kern_time.c 1.5 (2.11BSD) 2000/4/9
7: */
8:
9: #include "param.h"
10: #include "user.h"
11: #include "proc.h"
12: #include "kernel.h"
13: #include "systm.h"
14:
15: /*
16: * Time of day and interval timer support.
17: *
18: * These routines provide the kernel entry points to get and set
19: * the time-of-day.
20: */
21:
22: gettimeofday()
23: {
24: register struct a {
25: struct timeval *tp;
26: struct timezone *tzp;
27: } *uap = (struct a *)u.u_ap;
28: struct timeval atv;
29: int s;
30: register u_int ms;
31:
32: if (uap->tp) {
33: /*
34: * We don't resolve the milliseconds on every clock tick; it's
35: * easier to do it here. Long casts are out of paranoia.
36: */
37: s = splhigh(); atv = time; ms = lbolt; splx(s);
38: atv.tv_usec = (long)ms * mshz;
39: u.u_error = copyout((caddr_t)&atv, (caddr_t)(uap->tp),
40: sizeof(atv));
41: if (u.u_error)
42: return;
43: }
44: if (uap->tzp)
45: u.u_error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
46: sizeof (tz));
47: }
48:
49: settimeofday()
50: {
51: register struct a {
52: struct timeval *tv;
53: struct timezone *tzp;
54: } *uap = (struct a *)u.u_ap;
55: struct timeval atv;
56: struct timezone atz;
57:
58: if (uap->tv) {
59: u.u_error = copyin((caddr_t)uap->tv, (caddr_t)&atv,
60: sizeof (struct timeval));
61: if (u.u_error)
62: return;
63: setthetime(&atv);
64: if (u.u_error)
65: return;
66: }
67: if (uap->tzp && suser()) {
68: u.u_error = copyin((caddr_t)uap->tzp, (caddr_t)&atz,
69: sizeof (atz));
70: if (u.u_error == 0)
71: tz = atz;
72: }
73: }
74:
75: setthetime(tv)
76: register struct timeval *tv;
77: {
78: int s;
79:
80: if (!suser())
81: return;
82: #ifdef NOTNOW
83: /*
84: * If the system is secure, we do not allow the time to be set to an
85: * earlier value. The time may be slowed (using adjtime) but not set back.
86: *
87: * NOTE: Can not do this until ntpd is updated to deal with the coarse (50, 60
88: * hz) clocks. Ntpd wants to adjust time system clock a few microseconds
89: * at a time (which gets rounded to 0 in adjtime below). If that fails
90: * ntpd uses settimeofday to step the time backwards which obviously
91: * will fail if the next 'if' is enabled - all that does is fill up the
92: * logfiles with "can't set time" messages and the time keeps drifting.
93: */
94: if (securelevel > 0 && timercmp(tv, &time, <))
95: {
96: u.u_error = EPERM; /* XXX */
97: return;
98: }
99: #endif
100: /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
101: boottime.tv_sec += tv->tv_sec - time.tv_sec;
102: s = splhigh();
103: time = *tv; lbolt = time.tv_usec / mshz;
104: splx(s);
105: #ifdef notyet
106: /*
107: * if you have a time of day board, use it here
108: */
109: resettodr();
110: #endif
111: }
112:
113: adjtime()
114: {
115: register struct a {
116: struct timeval *delta;
117: struct timeval *olddelta;
118: } *uap = (struct a *)u.u_ap;
119: struct timeval atv;
120: register int s;
121: long adjust;
122:
123: if (!suser())
124: return;
125: u.u_error = copyin((caddr_t)uap->delta, (caddr_t)&atv,
126: sizeof (struct timeval));
127: if (u.u_error)
128: return;
129: adjust = (atv.tv_sec * hz) + (atv.tv_usec / mshz);
130: /* if unstoreable values, just set the clock */
131: if (adjust > 0x7fff || adjust < 0x8000) {
132: s = splclock();
133: time.tv_sec += atv.tv_sec;
134: lbolt += atv.tv_usec / mshz;
135: while (lbolt >= hz) {
136: lbolt -= hz;
137: ++time.tv_sec;
138: }
139: splx(s);
140: if (!uap->olddelta)
141: return;
142: atv.tv_sec = atv.tv_usec = 0;
143: } else {
144: if (!uap->olddelta) {
145: adjdelta = adjust;
146: return;
147: }
148: atv.tv_sec = adjdelta / hz;
149: atv.tv_usec = (adjdelta % hz) * mshz;
150: adjdelta = adjust;
151: }
152: (void) copyout((caddr_t)&atv, (caddr_t)uap->olddelta,
153: sizeof (struct timeval));
154: }
155:
156: getitimer()
157: {
158: register struct a {
159: u_int which;
160: struct itimerval *itv;
161: } *uap = (struct a *)u.u_ap;
162: struct itimerval aitv;
163: register int s;
164:
165: if (uap->which > ITIMER_PROF) {
166: u.u_error = EINVAL;
167: return;
168: }
169: aitv.it_interval.tv_usec = 0;
170: aitv.it_value.tv_usec = 0;
171: s = splclock();
172: if (uap->which == ITIMER_REAL) {
173: register struct proc *p = u.u_procp;
174:
175: aitv.it_interval.tv_sec = p->p_realtimer.it_interval;
176: aitv.it_value.tv_sec = p->p_realtimer.it_value;
177: }
178: else {
179: register struct k_itimerval *t = &u.u_timer[uap->which - 1];
180:
181: aitv.it_interval.tv_sec = t->it_interval / hz;
182: aitv.it_value.tv_sec = t->it_value / hz;
183: }
184: splx(s);
185: u.u_error = copyout((caddr_t)&aitv, (caddr_t)uap->itv,
186: sizeof (struct itimerval));
187: }
188:
189: setitimer()
190: {
191: register struct a {
192: u_int which;
193: struct itimerval *itv, *oitv;
194: } *uap = (struct a *)u.u_ap;
195: struct itimerval aitv;
196: register struct itimerval *aitvp;
197: int s;
198:
199: if (uap->which > ITIMER_PROF) {
200: u.u_error = EINVAL;
201: return;
202: }
203: aitvp = uap->itv;
204: if (uap->oitv) {
205: uap->itv = uap->oitv;
206: getitimer();
207: }
208: if (aitvp == 0)
209: return;
210: u.u_error = copyin((caddr_t)aitvp, (caddr_t)&aitv,
211: sizeof (struct itimerval));
212: if (u.u_error)
213: return;
214: s = splclock();
215: if (uap->which == ITIMER_REAL) {
216: register struct proc *p = u.u_procp;
217:
218: p->p_realtimer.it_value = aitv.it_value.tv_sec;
219: if (aitv.it_value.tv_usec)
220: ++p->p_realtimer.it_value;
221: p->p_realtimer.it_interval = aitv.it_interval.tv_sec;
222: if (aitv.it_interval.tv_usec)
223: ++p->p_realtimer.it_interval;
224: }
225: else {
226: register struct k_itimerval *t = &u.u_timer[uap->which - 1];
227:
228: t->it_value = aitv.it_value.tv_sec * hz;
229: if (aitv.it_value.tv_usec)
230: t->it_value += hz;
231: t->it_interval = aitv.it_interval.tv_sec * hz;
232: if (aitv.it_interval.tv_usec)
233: t->it_interval += hz;
234: }
235: splx(s);
236: }
237:
238: /*
239: * Check that a proposed value to load into the .it_value or
240: * .it_interval part of an interval timer is acceptable, and
241: * fix it to have at least minimal value (i.e. if it is less
242: * than the resolution of the clock, round it up.)
243: */
244: itimerfix(tv)
245: struct timeval *tv;
246: {
247:
248: if (tv->tv_sec < 0 || tv->tv_sec > 100000000L ||
249: tv->tv_usec < 0 || tv->tv_usec >= 1000000L)
250: return (EINVAL);
251: if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < (1000/hz))
252: tv->tv_usec = 1000/hz;
253: return (0);
254: }
255:
256: #ifdef NOT_CURRENTLY_IN_USE
257: /*
258: * Decrement an interval timer by a specified number
259: * of microseconds, which must be less than a second,
260: * i.e. < 1000000. If the timer expires, then reload
261: * it. In this case, carry over (usec - old value) to
262: * reducint the value reloaded into the timer so that
263: * the timer does not drift. This routine assumes
264: * that it is called in a context where the timers
265: * on which it is operating cannot change in value.
266: */
267: itimerdecr(itp, usec)
268: register struct itimerval *itp;
269: int usec;
270: {
271:
272: if (itp->it_value.tv_usec < usec) {
273: if (itp->it_value.tv_sec == 0) {
274: /* expired, and already in next interval */
275: usec -= itp->it_value.tv_usec;
276: goto expire;
277: }
278: itp->it_value.tv_usec += 1000000L;
279: itp->it_value.tv_sec--;
280: }
281: itp->it_value.tv_usec -= usec;
282: usec = 0;
283: if (timerisset(&itp->it_value))
284: return (1);
285: /* expired, exactly at end of interval */
286: expire:
287: if (timerisset(&itp->it_interval)) {
288: itp->it_value = itp->it_interval;
289: itp->it_value.tv_usec -= usec;
290: if (itp->it_value.tv_usec < 0) {
291: itp->it_value.tv_usec += 1000000L;
292: itp->it_value.tv_sec--;
293: }
294: } else
295: itp->it_value.tv_usec = 0; /* sec is already 0 */
296: return (0);
297: }
298: #endif /* NOT_CURRENTLY_IN_USE */
299:
300: #define timevalfix tvfix
301:
302: /*
303: * Add and subtract routines for timevals.
304: * N.B.: subtract routine doesn't deal with
305: * results which are before the beginning,
306: * it just gets very confused in this case.
307: * Caveat emptor.
308: */
309: timevaladd(t1, t2)
310: struct timeval *t1, *t2;
311: {
312:
313: t1->tv_sec += t2->tv_sec;
314: t1->tv_usec += t2->tv_usec;
315: timevalfix(t1);
316: }
317:
318: #ifdef NOT_CURRENTLY_IN_USE
319: timevalsub(t1, t2)
320: struct timeval *t1, *t2;
321: {
322:
323: t1->tv_sec -= t2->tv_sec;
324: t1->tv_usec -= t2->tv_usec;
325: timevalfix(t1);
326: }
327: #endif
328:
329: timevalfix(t1)
330: struct timeval *t1;
331: {
332:
333: if (t1->tv_usec < 0) {
334: t1->tv_sec--;
335: t1->tv_usec += 1000000L;
336: }
337: if (t1->tv_usec >= 1000000L) {
338: t1->tv_sec++;
339: t1->tv_usec -= 1000000L;
340: }
341: }
Defined functions
Defined struct's
a
defined in line
191; used 10 times
Defined macros