|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23: /*
24: * Copyright (c) 1982, 1986, 1989, 1993
25: * The Regents of the University of California. All rights reserved.
26: *
27: * Redistribution and use in source and binary forms, with or without
28: * modification, are permitted provided that the following conditions
29: * are met:
30: * 1. Redistributions of source code must retain the above copyright
31: * notice, this list of conditions and the following disclaimer.
32: * 2. Redistributions in binary form must reproduce the above copyright
33: * notice, this list of conditions and the following disclaimer in the
34: * documentation and/or other materials provided with the distribution.
35: * 3. All advertising materials mentioning features or use of this software
36: * must display the following acknowledgement:
37: * This product includes software developed by the University of
38: * California, Berkeley and its contributors.
39: * 4. Neither the name of the University nor the names of its contributors
40: * may be used to endorse or promote products derived from this software
41: * without specific prior written permission.
42: *
43: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53: * SUCH DAMAGE.
54: *
55: * @(#)kern_time.c 8.4 (Berkeley) 5/26/95
56: */
57:
58: #include <sys/param.h>
59: #include <sys/resourcevar.h>
60: #include <sys/kernel.h>
61: #include <sys/systm.h>
62: #include <sys/proc.h>
63: #include <sys/vnode.h>
64:
65: #include <sys/mount.h>
66:
67: #include <kern/cpu_number.h>
68:
69: #include <kern/clock.h>
70:
71: #define HZ 100 /* XXX */
72:
73: struct timeval time;
74:
75: /*
76: * Time of day and interval timer support.
77: *
78: * These routines provide the kernel entry points to get and set
79: * the time-of-day and per-process interval timers. Subroutines
80: * here provide support for adding and subtracting timeval structures
81: * and decrementing interval timers, optionally reloading the interval
82: * timers when they expire.
83: */
84: struct gettimeofday_args{
85: struct timeval *tp;
86: struct timezone *tzp;
87: };
88: /* ARGSUSED */
89: int
90: gettimeofday(p, uap, retval)
91: struct proc *p;
92: register struct gettimeofday_args *uap;
93: register_t *retval;
94: {
95: struct timeval atv;
96: int error = 0;
97:
98: if (uap->tp) {
99: microtime(&atv);
100: if (error = copyout((caddr_t)&atv, (caddr_t)uap->tp,
101: sizeof (atv)))
102: return(error);
103: }
104:
105: if (uap->tzp)
106: error = copyout((caddr_t)&tz, (caddr_t)uap->tzp,
107: sizeof (tz));
108:
109: return(error);
110: }
111:
112: struct settimeofday_args {
113: struct timeval *tv;
114: struct timezone *tzp;
115: };
116: /* ARGSUSED */
117: int
118: settimeofday(p, uap, retval)
119: struct proc *p;
120: struct settimeofday_args *uap;
121: register_t *retval;
122: {
123: struct timeval atv;
124: struct timezone atz;
125: int error, s;
126:
127: if (error = suser(p->p_ucred, &p->p_acflag))
128: return (error);
129: /* Verify all parameters before changing time. */
130: if (uap->tv && (error = copyin((caddr_t)uap->tv,
131: (caddr_t)&atv, sizeof(atv))))
132: return (error);
133: if (uap->tzp && (error = copyin((caddr_t)uap->tzp,
134: (caddr_t)&atz, sizeof(atz))))
135: return (error);
136: if (uap->tv)
137: setthetime(&atv);
138: if (uap->tzp)
139: tz = atz;
140: return (0);
141: }
142:
143: setthetime(tv)
144: struct timeval *tv;
145: {
146: mach_timespec_t now;
147: long delta;
148: int s;
149:
150: now.tv_sec = tv->tv_sec;
151: now.tv_nsec = tv->tv_usec * NSEC_PER_USEC;
152:
153: clock_set_calendar_value(now);
154: delta = tv->tv_sec - time.tv_sec;
155: boottime.tv_sec += delta;
156: #if NFSCLIENT || NFSSERVER
157: lease_updatetime(delta);
158: #endif
159: s = splhigh();
160: microtime(&time);
161: splx(s);
162: }
163:
164: int tickadj = 240000 / (60 * HZ); /* "standard" clock skew, us./tick */
165: int tickdelta; /* current clock skew, us. per tick */
166: long timedelta; /* unapplied time correction, us. */
167: long bigadj = 1000000; /* use 10x skew above bigadj us. */
168:
169: struct adjtime_args {
170: struct timeval *delta;
171: struct timeval *olddelta;
172: };
173: /* ARGSUSED */
174: int
175: adjtime(p, uap, retval)
176: struct proc *p;
177: register struct adjtime_args *uap;
178: register_t *retval;
179: {
180: struct timeval atv, oatv;
181: register long ndelta;
182: int s, error;
183:
184: if (error = suser(p->p_ucred, &p->p_acflag))
185: return (error);
186: if(error = copyin((caddr_t)uap->delta, (caddr_t)&atv,
187: sizeof (struct timeval)))
188: return(error);
189:
190: ndelta = atv.tv_sec * 1000000 + atv.tv_usec;
191: if (timedelta == 0)
192: if (ndelta > bigadj)
193: tickdelta = 10 * tickadj;
194: else
195: tickdelta = tickadj;
196: if (ndelta % tickdelta)
197: ndelta = ndelta / tickdelta * tickdelta;
198:
199: s = splclock();
200: if (uap->olddelta) {
201: oatv.tv_sec = timedelta / 1000000;
202: oatv.tv_usec = timedelta % 1000000;
203: }
204: timedelta = ndelta;
205: splx(s);
206:
207: if (uap->olddelta)
208: (void) copyout((caddr_t)&oatv, (caddr_t)uap->olddelta,
209: sizeof (struct timeval));
210: return(0);
211: }
212:
213: #define SECDAY ((unsigned)(24*60*60)) /* seconds per day */
214: #define SECYR ((unsigned)(365*SECDAY)) /* per common year */
215: #define YRREF 70 /* UNIX time referenced to 1970 */
216:
217: /*
218: * Initialze the time of day register, based on the time base which is, e.g.
219: * from a filesystem.
220: */
221: void
222: inittodr(base)
223: time_t base;
224: {
225: long deltat;
226:
227: if (base < (87-YRREF) * SECYR || base < 0) { /* fs < than 1987? */
228: printf("WARNING: preposterous time in file system");
229: goto check;
230: }
231:
232: /*
233: * Initialize the calendar by
234: * reading the BBC, if not already set.
235: */
236: clock_initialize_calendar();
237:
238: /*
239: * The value returned by microtime()
240: * is gotten from the calendar.
241: */
242: microtime(&time);
243:
244: /*
245: * This variable still exists to keep
246: * 'w' happy. It should only be considered
247: * an approximation.
248: */
249: boottime.tv_sec = time.tv_sec;
250: boottime.tv_usec = 0;
251:
252: /*
253: * See if we gained/lost two or more days;
254: * if so, assume something is amiss.
255: * Avoid changing RTC if RTC time > file system time and delta is
256: * less than two days.
257: */
258: deltat = time.tv_sec - base;
259: if (deltat < 0)
260: deltat = -deltat;
261: if ((deltat < 2*SECDAY) && (time.tv_sec > base))
262: return;
263: if (time.tv_sec < SECYR) {
264: printf ("WARNING: clock not set properly");
265: time.tv_sec = base;
266: time.tv_usec = 0;
267: setthetime(&time);
268: boottime = time;
269: goto check;
270: }
271:
272: if (deltat > 90*SECDAY) { /* assume rtc is way off */
273: printf ("WARNING: preposterous time in Real Time Clock");
274: time.tv_sec = base;
275: time.tv_usec = 0;
276: setthetime(&time);
277: boottime = time;
278: goto check;
279: }
280: printf("WARNING: clock lost %d days", deltat / SECDAY);
281: check:
282: printf(" -- CHECK AND RESET THE DATE!\n");
283: }
284:
285: /*
286: * Get value of an interval timer. The process virtual and
287: * profiling virtual time timers are kept in the u. area, since
288: * they can be swapped out. These are kept internally in the
289: * way they are specified externally: in time until they expire.
290: *
291: * The real time interval timer is kept in the process table slot
292: * for the process, and its value (it_value) is kept as an
293: * absolute time rather than as a delta, so that it is easy to keep
294: * periodic real-time signals from drifting.
295: *
296: * Virtual time timers are processed in the hardclock() routine of
297: * kern_clock.c. The real time timer is processed by a timeout
298: * routine, called from the softclock() routine. Since a callout
299: * may be delayed in real time due to interrupt processing in the system,
300: * it is possible for the real time timeout routine (realitexpire, given below),
301: * to be delayed in real time past when it is supposed to occur. It
302: * does not suffice, therefore, to reload the real timer .it_value from the
303: * real time timers .it_interval. Rather, we compute the next time in
304: * absolute time the timer should go off.
305: */
306:
307: struct getitimer_args {
308: u_int which;
309: struct itimerval *itv;
310: };
311: /* ARGSUSED */
312: int
313: getitimer(p, uap, retval)
314: struct proc *p;
315: register struct getitimer_args *uap;
316: register_t *retval;
317: {
318: struct itimerval aitv;
319: int s;
320:
321: if (uap->which > ITIMER_PROF)
322: return(EINVAL);
323:
324: s = splclock();
325: if (uap->which == ITIMER_REAL) {
326: /*
327: * Convert from absoulte to relative time in .it_value
328: * part of real time timer. If time for real time timer
329: * has passed return 0, else return difference between
330: * current time and time for the timer to go off.
331: */
332: aitv = p->p_realtimer;
333: if (timerisset(&aitv.it_value))
334: if (timercmp(&aitv.it_value, &time, <))
335: timerclear(&aitv.it_value);
336: else
337: timevalsub(&aitv.it_value, &time);
338: } else
339: aitv =p->p_stats->p_timer[uap->which];
340: splx(s);
341: return(copyout((caddr_t)&aitv, (caddr_t)uap->itv,
342: sizeof (struct itimerval)));
343: }
344:
345: struct setitimer_args {
346: u_int which;
347: struct itimerval *itv;
348: struct itimerval *oitv;
349: };
350: /* ARGSUSED */
351: int
352: setitimer(p, uap, retval)
353: struct proc *p;
354: register struct setitimer_args *uap;
355: register_t *retval;
356: {
357: struct itimerval aitv;
358: register struct itimerval *itvp;
359: int s, error;
360:
361: if (uap->which > ITIMER_PROF)
362: return(EINVAL);
363: itvp = uap->itv;
364: if (itvp && (error = copyin((caddr_t)itvp, (caddr_t)&aitv,
365: sizeof(struct itimerval))))
366: return (error);
367: if ((uap->itv = uap->oitv) &&
368: (error = getitimer(p, uap, retval)))
369: return (error);
370: if (itvp == 0)
371: return (0);
372: if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
373: return (EINVAL);
374: s = splclock();
375: if (uap->which == ITIMER_REAL) {
376: untimeout(realitexpire, (caddr_t)p);
377: if (timerisset(&aitv.it_value)) {
378: timevaladd(&aitv.it_value, &time);
379: timeout(realitexpire, (caddr_t)p, hzto(&aitv.it_value));
380: }
381: p->p_realtimer = aitv;
382: } else
383: p->p_stats->p_timer[uap->which] = aitv;
384: splx(s);
385: return(0); /* To insure good return value on success */
386: }
387:
388: /*
389: * Real interval timer expired:
390: * send process whose timer expired an alarm signal.
391: * If time is not set up to reload, then just return.
392: * Else compute next time timer should go off which is > current time.
393: * This is where delay in processing this timeout causes multiple
394: * SIGALRM calls to be compressed into one.
395: */
396: void
397: realitexpire(arg)
398: void *arg;
399: {
400: register struct proc *p;
401: int s;
402:
403: p = (struct proc *)arg;
404: psignal(p, SIGALRM);
405: if (!timerisset(&p->p_realtimer.it_interval)) {
406: timerclear(&p->p_realtimer.it_value);
407: return;
408: }
409:
410: /*
411: * If the time's way off, don't try to compensate by getting
412: * there incrementally.
413: */
414: s = splclock();
415: if (p->p_realtimer.it_value.tv_sec < time.tv_sec - 10) {
416: p->p_realtimer.it_value = time;
417: timeout(realitexpire, (caddr_t)p,
418: hzto(&p->p_realtimer.it_value));
419: splx(s);
420: return;
421:
422: }
423: splx(s);
424:
425: for (;;) {
426: s = splclock();
427: timevaladd(&p->p_realtimer.it_value,
428: &p->p_realtimer.it_interval);
429: if (timercmp(&p->p_realtimer.it_value, &time, >)) {
430: timeout(realitexpire, (caddr_t)p,
431: hzto(&p->p_realtimer.it_value));
432: splx(s);
433: return;
434: }
435: splx(s);
436: }
437: }
438:
439: /*
440: * Check that a proposed value to load into the .it_value or
441: * .it_interval part of an interval timer is acceptable, and
442: * fix it to have at least minimal value (i.e. if it is less
443: * than the resolution of the clock, round it up.)
444: */
445: int
446: itimerfix(tv)
447: struct timeval *tv;
448: {
449:
450: if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
451: tv->tv_usec < 0 || tv->tv_usec >= 1000000)
452: return (EINVAL);
453: if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
454: tv->tv_usec = tick;
455: return (0);
456: }
457:
458: /*
459: * Decrement an interval timer by a specified number
460: * of microseconds, which must be less than a second,
461: * i.e. < 1000000. If the timer expires, then reload
462: * it. In this case, carry over (usec - old value) to
463: * reducint the value reloaded into the timer so that
464: * the timer does not drift. This routine assumes
465: * that it is called in a context where the timers
466: * on which it is operating cannot change in value.
467: */
468: int
469: itimerdecr(itp, usec)
470: register struct itimerval *itp;
471: int usec;
472: {
473:
474: if (itp->it_value.tv_usec < usec) {
475: if (itp->it_value.tv_sec == 0) {
476: /* expired, and already in next interval */
477: usec -= itp->it_value.tv_usec;
478: goto expire;
479: }
480: itp->it_value.tv_usec += 1000000;
481: itp->it_value.tv_sec--;
482: }
483: itp->it_value.tv_usec -= usec;
484: usec = 0;
485: if (timerisset(&itp->it_value))
486: return (1);
487: /* expired, exactly at end of interval */
488: expire:
489: if (timerisset(&itp->it_interval)) {
490: itp->it_value = itp->it_interval;
491: itp->it_value.tv_usec -= usec;
492: if (itp->it_value.tv_usec < 0) {
493: itp->it_value.tv_usec += 1000000;
494: itp->it_value.tv_sec--;
495: }
496: } else
497: itp->it_value.tv_usec = 0; /* sec is already 0 */
498: return (0);
499: }
500:
501: /*
502: * Add and subtract routines for timevals.
503: * N.B.: subtract routine doesn't deal with
504: * results which are before the beginning,
505: * it just gets very confused in this case.
506: * Caveat emptor.
507: */
508: void
509: timevaladd(t1, t2)
510: struct timeval *t1, *t2;
511: {
512:
513: t1->tv_sec += t2->tv_sec;
514: t1->tv_usec += t2->tv_usec;
515: timevalfix(t1);
516: }
517: void
518: timevalsub(t1, t2)
519: struct timeval *t1, *t2;
520: {
521:
522: t1->tv_sec -= t2->tv_sec;
523: t1->tv_usec -= t2->tv_usec;
524: timevalfix(t1);
525: }
526: void
527: timevalfix(t1)
528: struct timeval *t1;
529: {
530:
531: if (t1->tv_usec < 0) {
532: t1->tv_sec--;
533: t1->tv_usec += 1000000;
534: }
535: if (t1->tv_usec >= 1000000) {
536: t1->tv_sec++;
537: t1->tv_usec -= 1000000;
538: }
539: }
540:
541: /*
542: * Return the best possible estimate of the time in the timeval
543: * to which tvp points.
544: */
545: void
546: microtime(struct timeval * tvp)
547: {
548: mach_timespec_t now = clock_get_calendar_value();
549:
550: tvp->tv_sec = now.tv_sec;
551: tvp->tv_usec = now.tv_nsec / NSEC_PER_USEC;
552: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.