2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
33 * Purpose: Routines for the creation and use of kernel
34 * alarm clock services. This file and the ipc
35 * routines in kern/ipc_clock.c constitute the
36 * machine-independent clock service layer.
39 #include <mach_host.h>
41 #include <mach/mach_types.h>
42 #include <mach/boolean.h>
43 #include <mach/processor_info.h>
44 #include <mach/vm_param.h>
46 #include <kern/cpu_number.h>
47 #include <kern/misc_protos.h>
48 #include <kern/lock.h>
49 #include <kern/host.h>
51 #include <kern/sched_prim.h>
52 #include <kern/thread.h>
53 #include <kern/ipc_host.h>
54 #include <kern/clock.h>
55 #include <kern/zalloc.h>
57 #include <ipc/ipc_types.h>
58 #include <ipc/ipc_port.h>
60 #include <mach/mach_traps.h>
61 #include <mach/clock_reply.h>
62 #include <mach/mach_time.h>
64 #include <mach/clock_server.h>
65 #include <mach/clock_priv_server.h>
66 #include <mach/host_priv_server.h>
72 #include <mach/clock_server.h>
73 #include <mach/mach_host_server.h>
75 /* local data declarations */
76 decl_simple_lock_data(static,ClockLock
) /* clock system synchronization */
77 static struct zone
*alarm_zone
; /* zone for user alarms */
78 static struct alarm
*alrmfree
; /* alarm free list pointer */
79 static struct alarm
*alrmdone
; /* alarm done list pointer */
80 static long alrm_seqno
; /* uniquely identifies alarms */
81 static thread_call_data_t alarm_deliver
;
83 decl_simple_lock_data(static,calend_adjlock
)
85 static timer_call_data_t calend_adjcall
;
86 static uint64_t calend_adjdeadline
;
88 static thread_call_data_t calend_wakecall
;
90 /* external declarations */
91 extern struct clock clock_list
[];
92 extern int clock_count
;
94 /* local clock subroutines */
106 alarm_type_t alarm_type
,
107 mach_timespec_t
*alarm_time
,
108 mach_timespec_t
*clock_time
);
111 void clock_alarm_deliver(
112 thread_call_param_t p0
,
113 thread_call_param_t p1
);
116 void calend_adjust_call(
117 timer_call_param_t p0
,
118 timer_call_param_t p1
);
121 void calend_dowakeup(
122 thread_call_param_t p0
,
123 thread_call_param_t p1
);
126 * Macros to lock/unlock clock system.
128 #define LOCK_CLOCK(s) \
130 simple_lock(&ClockLock);
132 #define UNLOCK_CLOCK(s) \
133 simple_unlock(&ClockLock); \
139 * Called once at boot to configure the clock subsystem.
147 assert(cpu_number() == master_cpu
);
149 simple_lock_init(&ClockLock
, 0);
150 thread_call_setup(&alarm_deliver
, clock_alarm_deliver
, NULL
);
152 simple_lock_init(&calend_adjlock
, 0);
153 timer_call_setup(&calend_adjcall
, calend_adjust_call
, NULL
);
155 thread_call_setup(&calend_wakecall
, calend_dowakeup
, NULL
);
158 * Configure clock devices.
160 for (i
= 0; i
< clock_count
; i
++) {
161 clock
= &clock_list
[i
];
163 if ((*clock
->cl_ops
->c_config
)() == 0)
169 * Initialize the timer callouts.
171 timer_call_initialize();
173 /* start alarm sequence numbers at 0 */
180 * Called on a processor each time started.
189 * Initialize basic clock structures.
191 for (i
= 0; i
< clock_count
; i
++) {
192 clock
= &clock_list
[i
];
193 if (clock
->cl_ops
&& clock
->cl_ops
->c_init
)
194 (*clock
->cl_ops
->c_init
)();
199 * Called by machine dependent code
200 * to initialize areas dependent on the
201 * timebase value. May be called multiple
202 * times during start up.
205 clock_timebase_init(void)
207 sched_timebase_init();
211 * Initialize the clock ipc service facility.
214 clock_service_create(void)
220 * Initialize ipc clock services.
222 for (i
= 0; i
< clock_count
; i
++) {
223 clock
= &clock_list
[i
];
225 ipc_clock_init(clock
);
226 ipc_clock_enable(clock
);
231 * Perform miscellaneous late
234 i
= sizeof(struct alarm
);
235 alarm_zone
= zinit(i
, (4096/i
)*i
, 10*i
, "alarms");
239 * Get the service port on a clock.
242 host_get_clock_service(
245 clock_t *clock
) /* OUT */
247 if (host
== HOST_NULL
|| clock_id
< 0 || clock_id
>= clock_count
) {
249 return (KERN_INVALID_ARGUMENT
);
252 *clock
= &clock_list
[clock_id
];
253 if ((*clock
)->cl_ops
== 0)
254 return (KERN_FAILURE
);
255 return (KERN_SUCCESS
);
259 * Get the control port on a clock.
262 host_get_clock_control(
263 host_priv_t host_priv
,
265 clock_t *clock
) /* OUT */
267 if (host_priv
== HOST_PRIV_NULL
|| clock_id
< 0 || clock_id
>= clock_count
) {
269 return (KERN_INVALID_ARGUMENT
);
272 *clock
= &clock_list
[clock_id
];
273 if ((*clock
)->cl_ops
== 0)
274 return (KERN_FAILURE
);
275 return (KERN_SUCCESS
);
279 * Get the current clock time.
284 mach_timespec_t
*cur_time
) /* OUT */
286 if (clock
== CLOCK_NULL
)
287 return (KERN_INVALID_ARGUMENT
);
288 return ((*clock
->cl_ops
->c_gettime
)(cur_time
));
292 * Get clock attributes.
295 clock_get_attributes(
297 clock_flavor_t flavor
,
298 clock_attr_t attr
, /* OUT */
299 mach_msg_type_number_t
*count
) /* IN/OUT */
301 if (clock
== CLOCK_NULL
)
302 return (KERN_INVALID_ARGUMENT
);
303 if (clock
->cl_ops
->c_getattr
)
304 return(clock
->cl_ops
->c_getattr(flavor
, attr
, count
));
306 return (KERN_FAILURE
);
310 * Set the current clock time.
315 mach_timespec_t new_time
)
317 mach_timespec_t
*clock_time
;
319 if (clock
== CLOCK_NULL
)
320 return (KERN_INVALID_ARGUMENT
);
321 if (clock
->cl_ops
->c_settime
== NULL
)
322 return (KERN_FAILURE
);
323 clock_time
= &new_time
;
324 if (BAD_MACH_TIMESPEC(clock_time
))
325 return (KERN_INVALID_VALUE
);
328 * Flush all outstanding alarms.
335 return (clock
->cl_ops
->c_settime(clock_time
));
339 * Set the clock alarm resolution.
342 clock_set_attributes(
344 clock_flavor_t flavor
,
346 mach_msg_type_number_t count
)
348 if (clock
== CLOCK_NULL
)
349 return (KERN_INVALID_ARGUMENT
);
350 if (clock
->cl_ops
->c_setattr
)
351 return (clock
->cl_ops
->c_setattr(flavor
, attr
, count
));
353 return (KERN_FAILURE
);
357 * Setup a clock alarm.
362 alarm_type_t alarm_type
,
363 mach_timespec_t alarm_time
,
364 ipc_port_t alarm_port
,
365 mach_msg_type_name_t alarm_port_type
)
368 mach_timespec_t clock_time
;
370 kern_return_t reply_code
;
373 if (clock
== CLOCK_NULL
)
374 return (KERN_INVALID_ARGUMENT
);
375 if (clock
->cl_ops
->c_setalrm
== 0)
376 return (KERN_FAILURE
);
377 if (IP_VALID(alarm_port
) == 0)
378 return (KERN_INVALID_CAPABILITY
);
381 * Check alarm parameters. If parameters are invalid,
382 * send alarm message immediately.
384 (*clock
->cl_ops
->c_gettime
)(&clock_time
);
385 chkstat
= check_time(alarm_type
, &alarm_time
, &clock_time
);
387 reply_code
= (chkstat
< 0 ? KERN_INVALID_VALUE
: KERN_SUCCESS
);
388 clock_alarm_reply(alarm_port
, alarm_port_type
,
389 reply_code
, alarm_type
, clock_time
);
390 return (KERN_SUCCESS
);
394 * Get alarm and add to clock alarm list.
398 if ((alarm
= alrmfree
) == 0) {
400 alarm
= (alarm_t
) zalloc(alarm_zone
);
402 return (KERN_RESOURCE_SHORTAGE
);
406 alrmfree
= alarm
->al_next
;
408 alarm
->al_status
= ALARM_CLOCK
;
409 alarm
->al_time
= alarm_time
;
410 alarm
->al_type
= alarm_type
;
411 alarm
->al_port
= alarm_port
;
412 alarm
->al_port_type
= alarm_port_type
;
413 alarm
->al_clock
= clock
;
414 alarm
->al_seqno
= alrm_seqno
++;
415 post_alarm(clock
, alarm
);
418 return (KERN_SUCCESS
);
422 * Sleep on a clock. System trap. User-level libmach clock_sleep
423 * interface call takes a mach_timespec_t sleep_time argument which it
424 * converts to sleep_sec and sleep_nsec arguments which are then
425 * passed to clock_sleep_trap.
429 struct clock_sleep_trap_args
*args
)
431 mach_port_name_t clock_name
= args
->clock_name
;
432 sleep_type_t sleep_type
= args
->sleep_type
;
433 int sleep_sec
= args
->sleep_sec
;
434 int sleep_nsec
= args
->sleep_nsec
;
435 mach_vm_address_t wakeup_time_addr
= args
->wakeup_time
;
437 mach_timespec_t swtime
;
438 kern_return_t rvalue
;
441 * Convert the trap parameters.
443 if (clock_name
!= MACH_PORT_NULL
)
444 clock
= port_name_to_clock(clock_name
);
446 clock
= &clock_list
[SYSTEM_CLOCK
];
448 swtime
.tv_sec
= sleep_sec
;
449 swtime
.tv_nsec
= sleep_nsec
;
452 * Call the actual clock_sleep routine.
454 rvalue
= clock_sleep_internal(clock
, sleep_type
, &swtime
);
457 * Return current time as wakeup time.
459 if (rvalue
!= KERN_INVALID_ARGUMENT
&& rvalue
!= KERN_FAILURE
) {
460 copyout((char *)&swtime
, wakeup_time_addr
, sizeof(mach_timespec_t
));
466 * Kernel internally callable clock sleep routine. The calling
467 * thread is suspended until the requested sleep time is reached.
470 clock_sleep_internal(
472 sleep_type_t sleep_type
,
473 mach_timespec_t
*sleep_time
)
476 mach_timespec_t clock_time
;
477 kern_return_t rvalue
;
481 if (clock
== CLOCK_NULL
)
482 return (KERN_INVALID_ARGUMENT
);
483 if (clock
->cl_ops
->c_setalrm
== 0)
484 return (KERN_FAILURE
);
487 * Check sleep parameters. If parameters are invalid
488 * return an error, otherwise post alarm request.
490 (*clock
->cl_ops
->c_gettime
)(&clock_time
);
492 chkstat
= check_time(sleep_type
, sleep_time
, &clock_time
);
494 return (KERN_INVALID_VALUE
);
495 rvalue
= KERN_SUCCESS
;
497 wait_result_t wait_result
;
500 * Get alarm and add to clock alarm list.
504 if ((alarm
= alrmfree
) == 0) {
506 alarm
= (alarm_t
) zalloc(alarm_zone
);
508 return (KERN_RESOURCE_SHORTAGE
);
512 alrmfree
= alarm
->al_next
;
515 * Wait for alarm to occur.
517 wait_result
= assert_wait((event_t
)alarm
, THREAD_ABORTSAFE
);
518 if (wait_result
== THREAD_WAITING
) {
519 alarm
->al_time
= *sleep_time
;
520 alarm
->al_status
= ALARM_SLEEP
;
521 post_alarm(clock
, alarm
);
524 wait_result
= thread_block(THREAD_CONTINUE_NULL
);
527 * Note if alarm expired normally or whether it
528 * was aborted. If aborted, delete alarm from
529 * clock alarm list. Return alarm to free list.
532 if (alarm
->al_status
!= ALARM_DONE
) {
533 assert(wait_result
!= THREAD_AWAKENED
);
534 if (((alarm
->al_prev
)->al_next
= alarm
->al_next
) != NULL
)
535 (alarm
->al_next
)->al_prev
= alarm
->al_prev
;
536 rvalue
= KERN_ABORTED
;
538 *sleep_time
= alarm
->al_time
;
539 alarm
->al_status
= ALARM_FREE
;
541 assert(wait_result
== THREAD_INTERRUPTED
);
542 assert(alarm
->al_status
== ALARM_FREE
);
543 rvalue
= KERN_ABORTED
;
545 alarm
->al_next
= alrmfree
;
550 *sleep_time
= clock_time
;
556 * CLOCK INTERRUPT SERVICE ROUTINES.
560 * Service clock alarm interrupts. Called from machine dependent
561 * layer at splclock(). The clock_id argument specifies the clock,
562 * and the clock_time argument gives that clock's current time.
567 mach_timespec_t
*clock_time
)
570 register alarm_t alrm1
;
571 register alarm_t alrm2
;
572 mach_timespec_t
*alarm_time
;
575 clock
= &clock_list
[clock_id
];
578 * Update clock alarm list. All alarms that are due are moved
579 * to the alarmdone list to be serviced by the alarm_thread.
583 alrm1
= (alarm_t
) &clock
->cl_alarm
;
584 while ((alrm2
= alrm1
->al_next
) != NULL
) {
585 alarm_time
= &alrm2
->al_time
;
586 if (CMP_MACH_TIMESPEC(alarm_time
, clock_time
) > 0)
590 * Alarm has expired, so remove it from the
593 if ((alrm1
->al_next
= alrm2
->al_next
) != NULL
)
594 (alrm1
->al_next
)->al_prev
= alrm1
;
597 * If a clock_sleep() alarm, wakeup the thread
598 * which issued the clock_sleep() call.
600 if (alrm2
->al_status
== ALARM_SLEEP
) {
602 alrm2
->al_status
= ALARM_DONE
;
603 alrm2
->al_time
= *clock_time
;
604 thread_wakeup((event_t
)alrm2
);
608 * If a clock_alarm() alarm, place the alarm on
609 * the alarm done list and schedule the alarm
610 * delivery mechanism.
613 assert(alrm2
->al_status
== ALARM_CLOCK
);
614 if ((alrm2
->al_next
= alrmdone
) != NULL
)
615 alrmdone
->al_prev
= alrm2
;
617 thread_call_enter(&alarm_deliver
);
618 alrm2
->al_prev
= (alarm_t
) &alrmdone
;
620 alrm2
->al_status
= ALARM_DONE
;
621 alrm2
->al_time
= *clock_time
;
626 * Setup the clock dependent layer to deliver another
627 * interrupt for the next pending alarm.
630 (*clock
->cl_ops
->c_setalrm
)(alarm_time
);
635 * ALARM DELIVERY ROUTINES.
640 __unused thread_call_param_t p0
,
641 __unused thread_call_param_t p1
)
643 register alarm_t alrm
;
648 while ((alrm
= alrmdone
) != NULL
) {
649 if ((alrmdone
= alrm
->al_next
) != NULL
)
650 alrmdone
->al_prev
= (alarm_t
) &alrmdone
;
653 code
= (alrm
->al_status
== ALARM_DONE
? KERN_SUCCESS
: KERN_ABORTED
);
654 if (alrm
->al_port
!= IP_NULL
) {
655 /* Deliver message to designated port */
656 if (IP_VALID(alrm
->al_port
)) {
657 clock_alarm_reply(alrm
->al_port
, alrm
->al_port_type
, code
,
658 alrm
->al_type
, alrm
->al_time
);
662 alrm
->al_status
= ALARM_FREE
;
663 alrm
->al_next
= alrmfree
;
667 panic("clock_alarm_deliver");
674 * CLOCK PRIVATE SERVICING SUBROUTINES.
678 * Flush all pending alarms on a clock. All alarms
679 * are activated and timestamped correctly, so any
680 * programs waiting on alarms/threads will proceed
681 * with accurate information.
688 register alarm_t alrm1
, alrm2
;
692 * Flush all outstanding alarms.
695 alrm1
= (alarm_t
) &clock
->cl_alarm
;
696 while ((alrm2
= alrm1
->al_next
) != NULL
) {
698 * Remove alarm from the clock alarm list.
700 if ((alrm1
->al_next
= alrm2
->al_next
) != NULL
)
701 (alrm1
->al_next
)->al_prev
= alrm1
;
704 * If a clock_sleep() alarm, wakeup the thread
705 * which issued the clock_sleep() call.
707 if (alrm2
->al_status
== ALARM_SLEEP
) {
709 thread_wakeup((event_t
)alrm2
);
713 * If a clock_alarm() alarm, place the alarm on
714 * the alarm done list and wakeup the dedicated
715 * kernel alarm_thread to service the alarm.
717 assert(alrm2
->al_status
== ALARM_CLOCK
);
718 if ((alrm2
->al_next
= alrmdone
) != NULL
)
719 alrmdone
->al_prev
= alrm2
;
721 thread_wakeup((event_t
)&alrmdone
);
722 alrm2
->al_prev
= (alarm_t
) &alrmdone
;
730 * Post an alarm on a clock's active alarm list. The alarm is
731 * inserted in time-order into the clock's active alarm list.
732 * Always called from within a LOCK_CLOCK() code section.
740 register alarm_t alrm1
, alrm2
;
741 mach_timespec_t
*alarm_time
;
742 mach_timespec_t
*queue_time
;
745 * Traverse alarm list until queue time is greater
746 * than alarm time, then insert alarm.
748 alarm_time
= &alarm
->al_time
;
749 alrm1
= (alarm_t
) &clock
->cl_alarm
;
750 while ((alrm2
= alrm1
->al_next
) != NULL
) {
751 queue_time
= &alrm2
->al_time
;
752 if (CMP_MACH_TIMESPEC(queue_time
, alarm_time
) > 0)
756 alrm1
->al_next
= alarm
;
757 alarm
->al_next
= alrm2
;
758 alarm
->al_prev
= alrm1
;
760 alrm2
->al_prev
= alarm
;
763 * If the inserted alarm is the 'earliest' alarm,
764 * reset the device layer alarm time accordingly.
766 if (clock
->cl_alarm
.al_next
== alarm
)
767 (*clock
->cl_ops
->c_setalrm
)(alarm_time
);
771 * Check the validity of 'alarm_time' and 'alarm_type'. If either
772 * argument is invalid, return a negative value. If the 'alarm_time'
773 * is now, return a 0 value. If the 'alarm_time' is in the future,
774 * return a positive value.
779 alarm_type_t alarm_type
,
780 mach_timespec_t
*alarm_time
,
781 mach_timespec_t
*clock_time
)
785 if (BAD_ALRMTYPE(alarm_type
))
787 if (BAD_MACH_TIMESPEC(alarm_time
))
789 if ((alarm_type
& ALRMTYPE
) == TIME_RELATIVE
)
790 ADD_MACH_TIMESPEC(alarm_time
, clock_time
);
792 result
= CMP_MACH_TIMESPEC(alarm_time
, clock_time
);
794 return ((result
>= 0)? result
: 0);
798 clock_get_system_value(void)
800 clock_t clock
= &clock_list
[SYSTEM_CLOCK
];
801 mach_timespec_t value
;
803 (void) (*clock
->cl_ops
->c_gettime
)(&value
);
809 clock_get_calendar_value(void)
811 clock_t clock
= &clock_list
[CALENDAR_CLOCK
];
812 mach_timespec_t value
= MACH_TIMESPEC_ZERO
;
814 (void) (*clock
->cl_ops
->c_gettime
)(&value
);
820 clock_deadline_for_periodic_event(
825 assert(interval
!= 0);
827 *deadline
+= interval
;
829 if (*deadline
<= abstime
) {
830 *deadline
= abstime
+ interval
;
831 abstime
= mach_absolute_time();
833 if (*deadline
<= abstime
)
834 *deadline
= abstime
+ interval
;
839 mk_timebase_info_trap(
840 struct mk_timebase_info_trap_args
*args
)
842 uint32_t *delta
= args
->delta
;
843 uint32_t *abs_to_ns_numer
= args
->abs_to_ns_numer
;
844 uint32_t *abs_to_ns_denom
= args
->abs_to_ns_denom
;
845 uint32_t *proc_to_abs_numer
= args
->proc_to_abs_numer
;
846 uint32_t *proc_to_abs_denom
= args
->proc_to_abs_denom
;
847 mach_timebase_info_data_t info
;
850 clock_timebase_info(&info
);
852 copyout((void *)&one
, CAST_USER_ADDR_T(delta
), sizeof (uint32_t));
854 copyout((void *)&info
.numer
, CAST_USER_ADDR_T(abs_to_ns_numer
), sizeof (uint32_t));
855 copyout((void *)&info
.denom
, CAST_USER_ADDR_T(abs_to_ns_denom
), sizeof (uint32_t));
857 copyout((void *)&one
, CAST_USER_ADDR_T(proc_to_abs_numer
), sizeof (uint32_t));
858 copyout((void *)&one
, CAST_USER_ADDR_T(proc_to_abs_denom
), sizeof (uint32_t));
862 mach_timebase_info_trap(
863 struct mach_timebase_info_trap_args
*args
)
865 mach_vm_address_t out_info_addr
= args
->info
;
866 mach_timebase_info_data_t info
;
868 clock_timebase_info(&info
);
870 copyout((void *)&info
, out_info_addr
, sizeof (info
));
872 return (KERN_SUCCESS
);
876 mach_wait_until_continue(
877 __unused
void *parameter
,
878 wait_result_t wresult
)
880 thread_syscall_return((wresult
== THREAD_INTERRUPTED
)? KERN_ABORTED
: KERN_SUCCESS
);
885 mach_wait_until_trap(
886 struct mach_wait_until_trap_args
*args
)
888 uint64_t deadline
= args
->deadline
;
889 wait_result_t wresult
;
891 wresult
= assert_wait_deadline((event_t
)mach_wait_until_trap
, THREAD_ABORTSAFE
, deadline
);
892 if (wresult
== THREAD_WAITING
)
893 wresult
= thread_block(mach_wait_until_continue
);
895 return ((wresult
== THREAD_INTERRUPTED
)? KERN_ABORTED
: KERN_SUCCESS
);
905 uint64_t now
= mach_absolute_time();
910 if ( (deadline
- now
) < (8 * sched_cswtime
) ||
911 get_preemption_level() != 0 ||
912 ml_get_interrupts_enabled() == FALSE
)
913 machine_delay_until(deadline
);
915 assert_wait_deadline((event_t
)clock_delay_until
, THREAD_UNINT
, deadline
- sched_cswtime
);
917 thread_block(THREAD_CONTINUE_NULL
);
924 uint32_t scale_factor
)
928 clock_interval_to_deadline(interval
, scale_factor
, &end
);
930 clock_delay_until(end
);
937 delay_for_interval((usec
< 0)? -usec
: usec
, NSEC_PER_USEC
);
949 simple_lock(&calend_adjlock
);
951 interval
= clock_set_calendar_adjtime(secs
, microsecs
);
953 if (calend_adjdeadline
>= interval
)
954 calend_adjdeadline
-= interval
;
955 clock_deadline_for_periodic_event(interval
, mach_absolute_time(),
956 &calend_adjdeadline
);
958 timer_call_enter(&calend_adjcall
, calend_adjdeadline
);
961 timer_call_cancel(&calend_adjcall
);
963 simple_unlock(&calend_adjlock
);
969 __unused timer_call_param_t p0
,
970 __unused timer_call_param_t p1
)
976 simple_lock(&calend_adjlock
);
978 interval
= clock_adjust_calendar();
980 clock_deadline_for_periodic_event(interval
, mach_absolute_time(),
981 &calend_adjdeadline
);
983 timer_call_enter(&calend_adjcall
, calend_adjdeadline
);
986 simple_unlock(&calend_adjlock
);
991 clock_wakeup_calendar(void)
993 thread_call_enter(&calend_wakecall
);
996 extern void IOKitResetTime(void); /* XXX */
1000 __unused thread_call_param_t p0
,
1001 __unused thread_call_param_t p1
)