2 * Copyright (c) 1993-2008 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/timer_queue.h>
39 #include <kern/call_entry.h>
41 #include <sys/kdebug.h>
43 #if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
47 decl_simple_lock_data(static,timer_call_lock
)
49 #define qe(x) ((queue_entry_t)(x))
50 #define TC(x) ((timer_call_t)(x))
53 timer_call_initialize(void)
55 simple_lock_init(&timer_call_lock
, 0);
61 timer_call_func_t func
,
62 timer_call_param_t param0
)
64 call_entry_setup(call
, func
, param0
);
68 call_entry_enqueue_deadline(
73 queue_t old_queue
= entry
->queue
;
76 if (old_queue
!= queue
|| entry
->deadline
< deadline
) {
77 if (old_queue
!= queue
)
78 current
= TC(queue_first(queue
));
80 current
= TC(queue_next(qe(entry
)));
82 if (old_queue
!= NULL
)
83 (void)remque(qe(entry
));
86 if ( queue_end(queue
, qe(current
)) ||
87 deadline
< current
->deadline
) {
88 current
= TC(queue_prev(qe(current
)));
92 current
= TC(queue_next(qe(current
)));
95 insque(qe(entry
), qe(current
));
98 if (deadline
< entry
->deadline
) {
99 current
= TC(queue_prev(qe(entry
)));
101 (void)remque(qe(entry
));
104 if ( queue_end(queue
, qe(current
)) ||
105 current
->deadline
<= deadline
) {
109 current
= TC(queue_prev(qe(current
)));
112 insque(qe(entry
), qe(current
));
115 entry
->queue
= queue
;
116 entry
->deadline
= deadline
;
122 call_entry_enqueue_tail(
126 queue_t old_queue
= entry
->queue
;
128 if (old_queue
!= NULL
)
129 (void)remque(qe(entry
));
131 enqueue_tail(queue
, qe(entry
));
133 entry
->queue
= queue
;
142 queue_t old_queue
= entry
->queue
;
144 if (old_queue
!= NULL
)
145 (void)remque(qe(entry
));
157 queue_t queue
, old_queue
;
161 simple_lock(&timer_call_lock
);
163 queue
= timer_queue_assign(deadline
);
165 old_queue
= call_entry_enqueue_deadline(call
, queue
, deadline
);
169 simple_unlock(&timer_call_lock
);
172 return (old_queue
!= NULL
);
178 timer_call_param_t param1
,
181 queue_t queue
, old_queue
;
185 simple_lock(&timer_call_lock
);
187 queue
= timer_queue_assign(deadline
);
189 old_queue
= call_entry_enqueue_deadline(call
, queue
, deadline
);
191 call
->param1
= param1
;
193 simple_unlock(&timer_call_lock
);
196 return (old_queue
!= NULL
);
207 simple_lock(&timer_call_lock
);
209 old_queue
= call_entry_dequeue(call
);
211 if (old_queue
!= NULL
) {
212 if (!queue_empty(old_queue
))
213 timer_queue_cancel(old_queue
, call
->deadline
, TC(queue_first(old_queue
))->deadline
);
215 timer_queue_cancel(old_queue
, call
->deadline
, UINT64_MAX
);
218 simple_unlock(&timer_call_lock
);
221 return (old_queue
!= NULL
);
225 timer_queue_shutdown(
233 simple_lock(&timer_call_lock
);
235 call
= TC(queue_first(queue
));
237 while (!queue_end(queue
, qe(call
))) {
238 new_queue
= timer_queue_assign(call
->deadline
);
240 call_entry_enqueue_deadline(call
, new_queue
, call
->deadline
);
242 call
= TC(queue_first(queue
));
245 simple_unlock(&timer_call_lock
);
256 simple_lock(&timer_call_lock
);
258 call
= TC(queue_first(queue
));
260 while (!queue_end(queue
, qe(call
))) {
261 if (call
->deadline
<= deadline
) {
262 timer_call_func_t func
;
263 timer_call_param_t param0
, param1
;
265 call_entry_dequeue(call
);
268 param0
= call
->param0
;
269 param1
= call
->param1
;
271 simple_unlock(&timer_call_lock
);
273 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI
,
280 #if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
281 DTRACE_TMR3(callout__start
, timer_call_func_t
, func
,
282 timer_call_param_t
, param0
,
283 timer_call_param_t
, param1
);
286 (*func
)(param0
, param1
);
288 #if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
289 DTRACE_TMR3(callout__end
, timer_call_func_t
, func
,
290 timer_call_param_t
, param0
,
291 timer_call_param_t
, param1
);
294 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI
,
301 simple_lock(&timer_call_lock
);
306 call
= TC(queue_first(queue
));
309 if (!queue_end(queue
, qe(call
)))
310 deadline
= call
->deadline
;
312 deadline
= UINT64_MAX
;
314 simple_unlock(&timer_call_lock
);