]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_time.c
2948aff9867aab93dcf29416cbde280c8370258f
[apple/xnu.git] / bsd / kern / kern_time.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
29 /*
30 * Copyright (c) 1982, 1986, 1989, 1993
31 * The Regents of the University of California. All rights reserved.
32 *
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
35 * are met:
36 * 1. Redistributions of source code must retain the above copyright
37 * notice, this list of conditions and the following disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 * 3. All advertising materials mentioning features or use of this software
42 * must display the following acknowledgement:
43 * This product includes software developed by the University of
44 * California, Berkeley and its contributors.
45 * 4. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * @(#)kern_time.c 8.4 (Berkeley) 5/26/95
62 */
63
64 #include <sys/param.h>
65 #include <sys/resourcevar.h>
66 #include <sys/kernel.h>
67 #include <sys/systm.h>
68 #include <sys/proc_internal.h>
69 #include <sys/kauth.h>
70 #include <sys/vnode.h>
71
72 #include <sys/mount_internal.h>
73 #include <sys/sysproto.h>
74 #include <sys/signalvar.h>
75
76 #include <kern/clock.h>
77 #include <kern/thread_call.h>
78
79 #define HZ 100 /* XXX */
80
81 /* simple lock used to access timezone, tz structure */
82 lck_spin_t * tz_slock;
83 lck_grp_t * tz_slock_grp;
84 lck_attr_t * tz_slock_attr;
85 lck_grp_attr_t *tz_slock_grp_attr;
86
87 static void setthetime(
88 struct timeval *tv);
89
90 void time_zone_slock_init(void);
91
92 int gettimeofday(struct proc *p,
93 #ifdef __ppc__
94 struct ppc_gettimeofday_args *uap,
95 #else
96 struct gettimeofday_args *uap,
97 #endif
98 register_t *retval);
99
100 /*
101 * Time of day and interval timer support.
102 *
103 * These routines provide the kernel entry points to get and set
104 * the time-of-day and per-process interval timers. Subroutines
105 * here provide support for adding and subtracting timeval structures
106 * and decrementing interval timers, optionally reloading the interval
107 * timers when they expire.
108 *
109 * XXX Y2038 bug because of clock_get_calendar_microtime() first argument
110 */
111 /* ARGSUSED */
112 int
113 gettimeofday(__unused struct proc *p,
114 #ifdef __ppc__
115 register struct ppc_gettimeofday_args *uap,
116 #else
117 register struct gettimeofday_args *uap,
118 #endif
119 __unused register_t *retval)
120 {
121 struct timeval atv;
122 int error = 0;
123 struct timezone ltz; /* local copy */
124
125 /* NOTE THIS implementation is for non ppc architectures only */
126
127 if (uap->tp) {
128 clock_get_calendar_microtime((uint32_t *)&atv.tv_sec, &atv.tv_usec);
129 if (IS_64BIT_PROCESS(p)) {
130 struct user_timeval user_atv;
131 user_atv.tv_sec = atv.tv_sec;
132 user_atv.tv_usec = atv.tv_usec;
133 /*
134 * This cast is not necessary for PPC, but is
135 * mostly harmless.
136 */
137 error = copyout(&user_atv, CAST_USER_ADDR_T(uap->tp), sizeof(struct user_timeval));
138 } else {
139 error = copyout(&atv, CAST_USER_ADDR_T(uap->tp), sizeof(struct timeval));
140 }
141 if (error)
142 return(error);
143 }
144
145 if (uap->tzp) {
146 lck_spin_lock(tz_slock);
147 ltz = tz;
148 lck_spin_unlock(tz_slock);
149 error = copyout((caddr_t)&ltz, CAST_USER_ADDR_T(uap->tzp),
150 sizeof (tz));
151 }
152
153 return(error);
154 }
155
156 /*
157 * XXX Y2038 bug because of setthetime() argument
158 */
159 /* ARGSUSED */
160 int
161 settimeofday(struct proc *p, struct settimeofday_args *uap, __unused register_t *retval)
162 {
163 struct timeval atv;
164 struct timezone atz;
165 int error;
166
167 if ((error = suser(kauth_cred_get(), &p->p_acflag)))
168 return (error);
169 /* Verify all parameters before changing time */
170 if (uap->tv) {
171 if (IS_64BIT_PROCESS(p)) {
172 struct user_timeval user_atv;
173 error = copyin(uap->tv, &user_atv, sizeof(struct user_timeval));
174 atv.tv_sec = user_atv.tv_sec;
175 atv.tv_usec = user_atv.tv_usec;
176 } else {
177 error = copyin(uap->tv, &atv, sizeof(struct timeval));
178 }
179 if (error)
180 return (error);
181 }
182 if (uap->tzp && (error = copyin(uap->tzp, (caddr_t)&atz, sizeof(atz))))
183 return (error);
184 if (uap->tv) {
185 timevalfix(&atv);
186 if (atv.tv_sec < 0 || (atv.tv_sec == 0 && atv.tv_usec < 0))
187 return (EPERM);
188 setthetime(&atv);
189 }
190 if (uap->tzp) {
191 lck_spin_lock(tz_slock);
192 tz = atz;
193 lck_spin_unlock(tz_slock);
194 }
195 return (0);
196 }
197
198 static void
199 setthetime(
200 struct timeval *tv)
201 {
202 clock_set_calendar_microtime(tv->tv_sec, tv->tv_usec);
203 }
204
205 /*
206 * XXX Y2038 bug because of clock_adjtime() first argument
207 */
208 /* ARGSUSED */
209 int
210 adjtime(struct proc *p, register struct adjtime_args *uap, __unused register_t *retval)
211 {
212 struct timeval atv;
213 int error;
214
215 if ((error = suser(kauth_cred_get(), &p->p_acflag)))
216 return (error);
217 if (IS_64BIT_PROCESS(p)) {
218 struct user_timeval user_atv;
219 error = copyin(uap->delta, &user_atv, sizeof(struct user_timeval));
220 atv.tv_sec = user_atv.tv_sec;
221 atv.tv_usec = user_atv.tv_usec;
222 } else {
223 error = copyin(uap->delta, &atv, sizeof(struct timeval));
224 }
225 if (error)
226 return (error);
227
228 /*
229 * Compute the total correction and the rate at which to apply it.
230 */
231 clock_adjtime((int32_t *)&atv.tv_sec, &atv.tv_usec);
232
233 if (uap->olddelta) {
234 if (IS_64BIT_PROCESS(p)) {
235 struct user_timeval user_atv;
236 user_atv.tv_sec = atv.tv_sec;
237 user_atv.tv_usec = atv.tv_usec;
238 error = copyout(&user_atv, uap->olddelta, sizeof(struct user_timeval));
239 } else {
240 error = copyout(&atv, uap->olddelta, sizeof(struct timeval));
241 }
242 }
243
244 return (0);
245 }
246
247 /*
248 * Verify the calendar value. If negative,
249 * reset to zero (the epoch).
250 */
251 void
252 inittodr(
253 __unused time_t base)
254 {
255 struct timeval tv;
256
257 /*
258 * Assertion:
259 * The calendar has already been
260 * set up from the platform clock.
261 *
262 * The value returned by microtime()
263 * is gotten from the calendar.
264 */
265 microtime(&tv);
266
267 if (tv.tv_sec < 0 || tv.tv_usec < 0) {
268 printf ("WARNING: preposterous time in Real Time Clock");
269 tv.tv_sec = 0; /* the UNIX epoch */
270 tv.tv_usec = 0;
271 setthetime(&tv);
272 printf(" -- CHECK AND RESET THE DATE!\n");
273 }
274 }
275
276 time_t
277 boottime_sec(void)
278 {
279 uint32_t sec, nanosec;
280 clock_get_boottime_nanotime(&sec, &nanosec);
281 return (sec);
282 }
283
284 uint64_t tvtoabstime(struct timeval *tvp);
285
286 /*
287 * Get value of an interval timer. The process virtual and
288 * profiling virtual time timers are kept internally in the
289 * way they are specified externally: in time until they expire.
290 *
291 * The real time interval timer expiration time (p_rtime)
292 * is kept as an absolute time rather than as a delta, so that
293 * it is easy to keep periodic real-time signals from drifting.
294 *
295 * Virtual time timers are processed in the hardclock() routine of
296 * kern_clock.c. The real time timer is processed by a callout
297 * routine. Since a callout may be delayed in real time due to
298 * other processing in the system, it is possible for the real
299 * time callout routine (realitexpire, given below), to be delayed
300 * in real time past when it is supposed to occur. It does not
301 * suffice, therefore, to reload the real time .it_value from the
302 * real time .it_interval. Rather, we compute the next time in
303 * absolute time when the timer should go off.
304 */
305
306 /* ARGSUSED */
307 int
308 getitimer(struct proc *p, register struct getitimer_args *uap, __unused register_t *retval)
309 {
310 struct itimerval aitv;
311
312 if (uap->which > ITIMER_PROF)
313 return(EINVAL);
314 if (uap->which == ITIMER_REAL) {
315 /*
316 * If time for real time timer has passed return 0,
317 * else return difference between current time and
318 * time for the timer to go off.
319 */
320 aitv = p->p_realtimer;
321 if (timerisset(&p->p_rtime)) {
322 struct timeval now;
323
324 microuptime(&now);
325 if (timercmp(&p->p_rtime, &now, <))
326 timerclear(&aitv.it_value);
327 else {
328 aitv.it_value = p->p_rtime;
329 timevalsub(&aitv.it_value, &now);
330 }
331 }
332 else
333 timerclear(&aitv.it_value);
334 }
335 else
336 aitv = p->p_stats->p_timer[uap->which];
337
338 if (IS_64BIT_PROCESS(p)) {
339 struct user_itimerval user_itv;
340 user_itv.it_interval.tv_sec = aitv.it_interval.tv_sec;
341 user_itv.it_interval.tv_usec = aitv.it_interval.tv_usec;
342 user_itv.it_value.tv_sec = aitv.it_value.tv_sec;
343 user_itv.it_value.tv_usec = aitv.it_value.tv_usec;
344 return (copyout((caddr_t)&user_itv, uap->itv, sizeof (struct user_itimerval)));
345 } else {
346 return (copyout((caddr_t)&aitv, uap->itv, sizeof (struct itimerval)));
347 }
348 }
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 user_addr_t itvp;
359 int error;
360
361 if (uap->which > ITIMER_PROF)
362 return (EINVAL);
363 if ((itvp = uap->itv)) {
364 if (IS_64BIT_PROCESS(p)) {
365 struct user_itimerval user_itv;
366 if ((error = copyin(itvp, (caddr_t)&user_itv, sizeof (struct user_itimerval))))
367 return (error);
368 aitv.it_interval.tv_sec = user_itv.it_interval.tv_sec;
369 aitv.it_interval.tv_usec = user_itv.it_interval.tv_usec;
370 aitv.it_value.tv_sec = user_itv.it_value.tv_sec;
371 aitv.it_value.tv_usec = user_itv.it_value.tv_usec;
372 } else {
373 if ((error = copyin(itvp, (caddr_t)&aitv, sizeof (struct itimerval))))
374 return (error);
375 }
376 }
377 if ((uap->itv = uap->oitv) && (error = getitimer(p, (struct getitimer_args *)uap, retval)))
378 return (error);
379 if (itvp == 0)
380 return (0);
381 if (itimerfix(&aitv.it_value) || itimerfix(&aitv.it_interval))
382 return (EINVAL);
383 if (uap->which == ITIMER_REAL) {
384 thread_call_func_cancel((thread_call_func_t)realitexpire, (void *)p->p_pid, FALSE);
385 if (timerisset(&aitv.it_value)) {
386 microuptime(&p->p_rtime);
387 timevaladd(&p->p_rtime, &aitv.it_value);
388 thread_call_func_delayed(
389 (thread_call_func_t)realitexpire, (void *)p->p_pid,
390 tvtoabstime(&p->p_rtime));
391 }
392 else
393 timerclear(&p->p_rtime);
394
395 p->p_realtimer = aitv;
396 }
397 else
398 p->p_stats->p_timer[uap->which] = aitv;
399
400 return (0);
401 }
402
403 /*
404 * Real interval timer expired:
405 * send process whose timer expired an alarm signal.
406 * If time is not set up to reload, then just return.
407 * Else compute next time timer should go off which is > current time.
408 * This is where delay in processing this timeout causes multiple
409 * SIGALRM calls to be compressed into one.
410 */
411 void
412 realitexpire(
413 void *pid)
414 {
415 register struct proc *p;
416 struct timeval now;
417 boolean_t funnel_state;
418
419 funnel_state = thread_funnel_set(kernel_flock, TRUE);
420 p = pfind((pid_t)pid);
421 if (p == NULL) {
422 (void) thread_funnel_set(kernel_flock, FALSE);
423 return;
424 }
425
426 if (!timerisset(&p->p_realtimer.it_interval)) {
427 timerclear(&p->p_rtime);
428 psignal(p, SIGALRM);
429
430 (void) thread_funnel_set(kernel_flock, FALSE);
431 return;
432 }
433
434 microuptime(&now);
435 timevaladd(&p->p_rtime, &p->p_realtimer.it_interval);
436 if (timercmp(&p->p_rtime, &now, <=)) {
437 if ((p->p_rtime.tv_sec + 2) >= now.tv_sec) {
438 for (;;) {
439 timevaladd(&p->p_rtime, &p->p_realtimer.it_interval);
440 if (timercmp(&p->p_rtime, &now, >))
441 break;
442 }
443 }
444 else {
445 p->p_rtime = p->p_realtimer.it_interval;
446 timevaladd(&p->p_rtime, &now);
447 }
448 }
449
450 psignal(p, SIGALRM);
451
452 thread_call_func_delayed((thread_call_func_t)realitexpire, pid, tvtoabstime(&p->p_rtime));
453
454 (void) thread_funnel_set(kernel_flock, FALSE);
455 }
456
457 /*
458 * Check that a proposed value to load into the .it_value or
459 * .it_interval part of an interval timer is acceptable, and
460 * fix it to have at least minimal value (i.e. if it is less
461 * than the resolution of the clock, round it up.)
462 */
463 int
464 itimerfix(tv)
465 struct timeval *tv;
466 {
467
468 if (tv->tv_sec < 0 || tv->tv_sec > 100000000 ||
469 tv->tv_usec < 0 || tv->tv_usec >= 1000000)
470 return (EINVAL);
471 if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
472 tv->tv_usec = tick;
473 return (0);
474 }
475
476 /*
477 * Decrement an interval timer by a specified number
478 * of microseconds, which must be less than a second,
479 * i.e. < 1000000. If the timer expires, then reload
480 * it. In this case, carry over (usec - old value) to
481 * reducint the value reloaded into the timer so that
482 * the timer does not drift. This routine assumes
483 * that it is called in a context where the timers
484 * on which it is operating cannot change in value.
485 */
486 int
487 itimerdecr(itp, usec)
488 register struct itimerval *itp;
489 int usec;
490 {
491
492 if (itp->it_value.tv_usec < usec) {
493 if (itp->it_value.tv_sec == 0) {
494 /* expired, and already in next interval */
495 usec -= itp->it_value.tv_usec;
496 goto expire;
497 }
498 itp->it_value.tv_usec += 1000000;
499 itp->it_value.tv_sec--;
500 }
501 itp->it_value.tv_usec -= usec;
502 usec = 0;
503 if (timerisset(&itp->it_value))
504 return (1);
505 /* expired, exactly at end of interval */
506 expire:
507 if (timerisset(&itp->it_interval)) {
508 itp->it_value = itp->it_interval;
509 itp->it_value.tv_usec -= usec;
510 if (itp->it_value.tv_usec < 0) {
511 itp->it_value.tv_usec += 1000000;
512 itp->it_value.tv_sec--;
513 }
514 } else
515 itp->it_value.tv_usec = 0; /* sec is already 0 */
516 return (0);
517 }
518
519 /*
520 * Add and subtract routines for timevals.
521 * N.B.: subtract routine doesn't deal with
522 * results which are before the beginning,
523 * it just gets very confused in this case.
524 * Caveat emptor.
525 */
526 void
527 timevaladd(
528 struct timeval *t1,
529 struct timeval *t2)
530 {
531
532 t1->tv_sec += t2->tv_sec;
533 t1->tv_usec += t2->tv_usec;
534 timevalfix(t1);
535 }
536 void
537 timevalsub(
538 struct timeval *t1,
539 struct timeval *t2)
540 {
541
542 t1->tv_sec -= t2->tv_sec;
543 t1->tv_usec -= t2->tv_usec;
544 timevalfix(t1);
545 }
546 void
547 timevalfix(
548 struct timeval *t1)
549 {
550
551 if (t1->tv_usec < 0) {
552 t1->tv_sec--;
553 t1->tv_usec += 1000000;
554 }
555 if (t1->tv_usec >= 1000000) {
556 t1->tv_sec++;
557 t1->tv_usec -= 1000000;
558 }
559 }
560
561 /*
562 * Return the best possible estimate of the time in the timeval
563 * to which tvp points.
564 */
565 void
566 microtime(
567 struct timeval *tvp)
568 {
569 clock_get_calendar_microtime((uint32_t *)&tvp->tv_sec, &tvp->tv_usec);
570 }
571
572 void
573 microuptime(
574 struct timeval *tvp)
575 {
576 clock_get_system_microtime((uint32_t *)&tvp->tv_sec, &tvp->tv_usec);
577 }
578
579 /*
580 * Ditto for timespec.
581 */
582 void
583 nanotime(
584 struct timespec *tsp)
585 {
586 clock_get_calendar_nanotime((uint32_t *)&tsp->tv_sec, (uint32_t *)&tsp->tv_nsec);
587 }
588
589 void
590 nanouptime(
591 struct timespec *tsp)
592 {
593 clock_get_system_nanotime((uint32_t *)&tsp->tv_sec, (uint32_t *)&tsp->tv_nsec);
594 }
595
596 uint64_t
597 tvtoabstime(
598 struct timeval *tvp)
599 {
600 uint64_t result, usresult;
601
602 clock_interval_to_absolutetime_interval(
603 tvp->tv_sec, NSEC_PER_SEC, &result);
604 clock_interval_to_absolutetime_interval(
605 tvp->tv_usec, NSEC_PER_USEC, &usresult);
606
607 return (result + usresult);
608 }
609 void
610 time_zone_slock_init(void)
611 {
612 /* allocate lock group attribute and group */
613 tz_slock_grp_attr = lck_grp_attr_alloc_init();
614 lck_grp_attr_setstat(tz_slock_grp_attr);
615
616 tz_slock_grp = lck_grp_alloc_init("tzlock", tz_slock_grp_attr);
617
618 /* Allocate lock attribute */
619 tz_slock_attr = lck_attr_alloc_init();
620 //lck_attr_setdebug(tz_slock_attr);
621
622 /* Allocate the spin lock */
623 tz_slock = lck_spin_alloc_init(tz_slock_grp, tz_slock_attr);
624 }
625