2 * Copyright (c) 1993-2007 Apple 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@
29 * Timer interrupt callout module.
32 #include <mach/mach_types.h>
34 #include <kern/clock.h>
35 #include <kern/processor.h>
36 #include <kern/etimer.h>
37 #include <kern/timer_call.h>
38 #include <kern/call_entry.h>
40 #include <sys/kdebug.h>
42 #if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
46 decl_simple_lock_data(static,timer_call_lock
)
52 #define qe(x) ((queue_entry_t)(x))
53 #define TC(x) ((timer_call_t)(x))
56 timer_call_initialize(void)
60 simple_lock_init(&timer_call_lock
, 0);
63 simple_lock(&timer_call_lock
);
65 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
67 simple_unlock(&timer_call_lock
);
74 timer_call_func_t func
,
75 timer_call_param_t param0
)
77 call_entry_setup(call
, func
, param0
);
82 _delayed_call_enqueue(
88 current
= TC(queue_first(queue
));
91 if ( queue_end(queue
, qe(current
)) ||
92 call
->deadline
< current
->deadline
) {
93 current
= TC(queue_prev(qe(current
)));
97 current
= TC(queue_next(qe(current
)));
100 insque(qe(call
), qe(current
));
102 call
->state
= DELAYED
;
107 _delayed_call_dequeue(
110 (void)remque(qe(call
));
117 _set_delayed_call_timer(
120 etimer_set_deadline(call
->deadline
);
128 boolean_t result
= TRUE
;
133 simple_lock(&timer_call_lock
);
135 if (call
->state
== DELAYED
)
136 _delayed_call_dequeue(call
);
141 call
->deadline
= deadline
;
143 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
145 _delayed_call_enqueue(queue
, call
);
147 if (queue_first(queue
) == qe(call
))
148 _set_delayed_call_timer(call
);
150 simple_unlock(&timer_call_lock
);
159 timer_call_param_t param1
,
162 boolean_t result
= TRUE
;
167 simple_lock(&timer_call_lock
);
169 if (call
->state
== DELAYED
)
170 _delayed_call_dequeue(call
);
174 call
->param1
= param1
;
175 call
->deadline
= deadline
;
177 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
179 _delayed_call_enqueue(queue
, call
);
181 if (queue_first(queue
) == qe(call
))
182 _set_delayed_call_timer(call
);
184 simple_unlock(&timer_call_lock
);
194 boolean_t result
= TRUE
;
198 simple_lock(&timer_call_lock
);
200 if (call
->state
== DELAYED
) {
201 queue_t queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
203 if (queue_first(queue
) == qe(call
)) {
204 _delayed_call_dequeue(call
);
206 if (!queue_empty(queue
))
207 _set_delayed_call_timer((timer_call_t
)queue_first(queue
));
210 _delayed_call_dequeue(call
);
215 simple_unlock(&timer_call_lock
);
222 timer_call_is_delayed(
226 boolean_t result
= FALSE
;
230 simple_lock(&timer_call_lock
);
232 if (call
->state
== DELAYED
) {
233 if (deadline
!= NULL
)
234 *deadline
= call
->deadline
;
238 simple_unlock(&timer_call_lock
);
245 * Called at splclock.
250 processor_t processor
)
253 queue_t queue
, myqueue
;
255 assert(processor
!= current_processor());
257 queue
= &PROCESSOR_DATA(processor
, timer_call_queue
);
258 myqueue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
260 simple_lock(&timer_call_lock
);
262 call
= TC(queue_first(queue
));
264 while (!queue_end(queue
, qe(call
))) {
265 _delayed_call_dequeue(call
);
267 _delayed_call_enqueue(myqueue
, call
);
269 call
= TC(queue_first(queue
));
272 call
= TC(queue_first(myqueue
));
274 if (!queue_end(myqueue
, qe(call
)))
275 _set_delayed_call_timer(call
);
277 simple_unlock(&timer_call_lock
);
281 timer_call_interrupt(uint64_t timestamp
)
286 simple_lock(&timer_call_lock
);
288 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
290 call
= TC(queue_first(queue
));
292 while (!queue_end(queue
, qe(call
))) {
293 if (call
->deadline
<= timestamp
) {
294 timer_call_func_t func
;
295 timer_call_param_t param0
, param1
;
297 _delayed_call_dequeue(call
);
300 param0
= call
->param0
;
301 param1
= call
->param1
;
303 simple_unlock(&timer_call_lock
);
305 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI
,
309 (unsigned int)param0
,
310 (unsigned int)param1
, 0, 0);
312 #if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
313 DTRACE_TMR3(callout__start
, timer_call_func_t
, func
,
314 timer_call_param_t
, param0
,
315 timer_call_param_t
, param1
);
318 (*func
)(param0
, param1
);
320 #if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
321 DTRACE_TMR3(callout__end
, timer_call_func_t
, func
,
322 timer_call_param_t
, param0
,
323 timer_call_param_t
, param1
);
326 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI
,
330 (unsigned int)param0
,
331 (unsigned int)param1
, 0, 0);
333 simple_lock(&timer_call_lock
);
337 call
= TC(queue_first(queue
));
340 if (!queue_end(queue
, qe(call
)))
341 _set_delayed_call_timer(call
);
343 simple_unlock(&timer_call_lock
);