]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_time.c
0f225ed525a41148ba9dc1f9d9a3cce156af0e9e
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1982, 1986, 1989, 1993
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
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.
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
55 * @(#)kern_time.c 8.4 (Berkeley) 5/26/95
58 #include <sys/param.h>
59 #include <sys/resourcevar.h>
60 #include <sys/kernel.h>
61 #include <sys/systm.h>
63 #include <sys/vnode.h>
65 #include <sys/mount.h>
67 #include <kern/cpu_number.h>
69 #include <kern/clock.h>
71 #define HZ 100 /* XXX */
76 * Time of day and interval timer support.
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.
84 struct gettimeofday_args
{
90 gettimeofday(p
, uap
, retval
)
92 register struct gettimeofday_args
*uap
;
100 if (error
= copyout((caddr_t
)&atv
, (caddr_t
)uap
->tp
,
106 error
= copyout((caddr_t
)&tz
, (caddr_t
)uap
->tzp
,
112 struct settimeofday_args
{
114 struct timezone
*tzp
;
118 settimeofday(p
, uap
, retval
)
120 struct settimeofday_args
*uap
;
127 if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
129 /* Verify all parameters before changing time. */
130 if (uap
->tv
&& (error
= copyin((caddr_t
)uap
->tv
,
131 (caddr_t
)&atv
, sizeof(atv
))))
133 if (uap
->tzp
&& (error
= copyin((caddr_t
)uap
->tzp
,
134 (caddr_t
)&atz
, sizeof(atz
))))
150 now
.tv_sec
= tv
->tv_sec
;
151 now
.tv_nsec
= tv
->tv_usec
* NSEC_PER_USEC
;
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
);
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. */
169 struct adjtime_args
{
170 struct timeval
*delta
;
171 struct timeval
*olddelta
;
175 adjtime(p
, uap
, retval
)
177 register struct adjtime_args
*uap
;
180 struct timeval atv
, oatv
;
181 register long ndelta
;
184 if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
186 if(error
= copyin((caddr_t
)uap
->delta
, (caddr_t
)&atv
,
187 sizeof (struct timeval
)))
190 ndelta
= atv
.tv_sec
* 1000000 + atv
.tv_usec
;
193 tickdelta
= 10 * tickadj
;
196 if (ndelta
% tickdelta
)
197 ndelta
= ndelta
/ tickdelta
* tickdelta
;
201 oatv
.tv_sec
= timedelta
/ 1000000;
202 oatv
.tv_usec
= timedelta
% 1000000;
208 (void) copyout((caddr_t
)&oatv
, (caddr_t
)uap
->olddelta
,
209 sizeof (struct timeval
));
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 */
218 * Initialze the time of day register.
219 * Trust the RTC except for the case where it is set before
220 * the UNIX epoch. In that case use the the UNIX epoch.
221 * The argument passed in is ignored.
228 * Initialize the calendar by
229 * reading the BBC, if not already set.
231 clock_initialize_calendar();
234 * The value returned by microtime()
235 * is gotten from the calendar.
240 * This variable still exists to keep
241 * 'w' happy. It should only be considered
244 boottime
.tv_sec
= time
.tv_sec
;
245 boottime
.tv_usec
= 0;
248 * If the RTC does not have acceptable value, i.e. time before
249 * the UNIX epoch, set it to the UNIX epoch
251 if (time
.tv_sec
< 0) {
252 printf ("WARNING: preposterous time in Real Time Clock");
253 time
.tv_sec
= 0; /* the UNIX epoch */
257 printf(" -- CHECK AND RESET THE DATE!\n");
264 * Get value of an interval timer. The process virtual and
265 * profiling virtual time timers are kept in the u. area, since
266 * they can be swapped out. These are kept internally in the
267 * way they are specified externally: in time until they expire.
269 * The real time interval timer is kept in the process table slot
270 * for the process, and its value (it_value) is kept as an
271 * absolute time rather than as a delta, so that it is easy to keep
272 * periodic real-time signals from drifting.
274 * Virtual time timers are processed in the hardclock() routine of
275 * kern_clock.c. The real time timer is processed by a timeout
276 * routine, called from the softclock() routine. Since a callout
277 * may be delayed in real time due to interrupt processing in the system,
278 * it is possible for the real time timeout routine (realitexpire, given below),
279 * to be delayed in real time past when it is supposed to occur. It
280 * does not suffice, therefore, to reload the real timer .it_value from the
281 * real time timers .it_interval. Rather, we compute the next time in
282 * absolute time the timer should go off.
285 struct getitimer_args
{
287 struct itimerval
*itv
;
291 getitimer(p
, uap
, retval
)
293 register struct getitimer_args
*uap
;
296 struct itimerval aitv
;
299 if (uap
->which
> ITIMER_PROF
)
303 if (uap
->which
== ITIMER_REAL
) {
305 * Convert from absoulte to relative time in .it_value
306 * part of real time timer. If time for real time timer
307 * has passed return 0, else return difference between
308 * current time and time for the timer to go off.
310 aitv
= p
->p_realtimer
;
311 if (timerisset(&aitv
.it_value
))
312 if (timercmp(&aitv
.it_value
, &time
, <))
313 timerclear(&aitv
.it_value
);
315 timevalsub(&aitv
.it_value
, &time
);
317 aitv
=p
->p_stats
->p_timer
[uap
->which
];
319 return(copyout((caddr_t
)&aitv
, (caddr_t
)uap
->itv
,
320 sizeof (struct itimerval
)));
323 struct setitimer_args
{
325 struct itimerval
*itv
;
326 struct itimerval
*oitv
;
330 setitimer(p
, uap
, retval
)
332 register struct setitimer_args
*uap
;
335 struct itimerval aitv
;
336 register struct itimerval
*itvp
;
339 if (uap
->which
> ITIMER_PROF
)
342 if (itvp
&& (error
= copyin((caddr_t
)itvp
, (caddr_t
)&aitv
,
343 sizeof(struct itimerval
))))
345 if ((uap
->itv
= uap
->oitv
) &&
346 (error
= getitimer(p
, uap
, retval
)))
350 if (itimerfix(&aitv
.it_value
) || itimerfix(&aitv
.it_interval
))
353 if (uap
->which
== ITIMER_REAL
) {
354 untimeout(realitexpire
, (caddr_t
)p
);
355 if (timerisset(&aitv
.it_value
)) {
356 timevaladd(&aitv
.it_value
, &time
);
357 timeout(realitexpire
, (caddr_t
)p
, hzto(&aitv
.it_value
));
359 p
->p_realtimer
= aitv
;
361 p
->p_stats
->p_timer
[uap
->which
] = aitv
;
363 return(0); /* To insure good return value on success */
367 * Real interval timer expired:
368 * send process whose timer expired an alarm signal.
369 * If time is not set up to reload, then just return.
370 * Else compute next time timer should go off which is > current time.
371 * This is where delay in processing this timeout causes multiple
372 * SIGALRM calls to be compressed into one.
378 register struct proc
*p
;
380 boolean_t funnel_state
;
382 funnel_state
= thread_funnel_set(kernel_flock
,TRUE
);
384 p
= (struct proc
*)arg
;
386 if (!timerisset(&p
->p_realtimer
.it_interval
)) {
387 timerclear(&p
->p_realtimer
.it_value
);
388 (void) thread_funnel_set(kernel_flock
, FALSE
);
393 * If the time's way off, don't try to compensate by getting
394 * there incrementally.
397 if (p
->p_realtimer
.it_value
.tv_sec
< time
.tv_sec
- 10) {
398 p
->p_realtimer
.it_value
= time
;
399 timeout(realitexpire
, (caddr_t
)p
,
400 hzto(&p
->p_realtimer
.it_value
));
402 (void) thread_funnel_set(kernel_flock
, FALSE
);
410 timevaladd(&p
->p_realtimer
.it_value
,
411 &p
->p_realtimer
.it_interval
);
412 if (timercmp(&p
->p_realtimer
.it_value
, &time
, >)) {
413 timeout(realitexpire
, (caddr_t
)p
,
414 hzto(&p
->p_realtimer
.it_value
));
416 (void) thread_funnel_set(kernel_flock
, FALSE
);
422 (void) thread_funnel_set(kernel_flock
, FALSE
);
426 * Check that a proposed value to load into the .it_value or
427 * .it_interval part of an interval timer is acceptable, and
428 * fix it to have at least minimal value (i.e. if it is less
429 * than the resolution of the clock, round it up.)
436 if (tv
->tv_sec
< 0 || tv
->tv_sec
> 100000000 ||
437 tv
->tv_usec
< 0 || tv
->tv_usec
>= 1000000)
439 if (tv
->tv_sec
== 0 && tv
->tv_usec
!= 0 && tv
->tv_usec
< tick
)
445 * Decrement an interval timer by a specified number
446 * of microseconds, which must be less than a second,
447 * i.e. < 1000000. If the timer expires, then reload
448 * it. In this case, carry over (usec - old value) to
449 * reducint the value reloaded into the timer so that
450 * the timer does not drift. This routine assumes
451 * that it is called in a context where the timers
452 * on which it is operating cannot change in value.
455 itimerdecr(itp
, usec
)
456 register struct itimerval
*itp
;
460 if (itp
->it_value
.tv_usec
< usec
) {
461 if (itp
->it_value
.tv_sec
== 0) {
462 /* expired, and already in next interval */
463 usec
-= itp
->it_value
.tv_usec
;
466 itp
->it_value
.tv_usec
+= 1000000;
467 itp
->it_value
.tv_sec
--;
469 itp
->it_value
.tv_usec
-= usec
;
471 if (timerisset(&itp
->it_value
))
473 /* expired, exactly at end of interval */
475 if (timerisset(&itp
->it_interval
)) {
476 itp
->it_value
= itp
->it_interval
;
477 itp
->it_value
.tv_usec
-= usec
;
478 if (itp
->it_value
.tv_usec
< 0) {
479 itp
->it_value
.tv_usec
+= 1000000;
480 itp
->it_value
.tv_sec
--;
483 itp
->it_value
.tv_usec
= 0; /* sec is already 0 */
488 * Add and subtract routines for timevals.
489 * N.B.: subtract routine doesn't deal with
490 * results which are before the beginning,
491 * it just gets very confused in this case.
496 struct timeval
*t1
, *t2
;
499 t1
->tv_sec
+= t2
->tv_sec
;
500 t1
->tv_usec
+= t2
->tv_usec
;
505 struct timeval
*t1
, *t2
;
508 t1
->tv_sec
-= t2
->tv_sec
;
509 t1
->tv_usec
-= t2
->tv_usec
;
517 if (t1
->tv_usec
< 0) {
519 t1
->tv_usec
+= 1000000;
521 if (t1
->tv_usec
>= 1000000) {
523 t1
->tv_usec
-= 1000000;
528 * Return the best possible estimate of the time in the timeval
529 * to which tvp points.
532 microtime(struct timeval
* tvp
)
534 mach_timespec_t now
= clock_get_calendar_value();
536 tvp
->tv_sec
= now
.tv_sec
;
537 tvp
->tv_usec
= now
.tv_nsec
/ NSEC_PER_USEC
;