2 * Copyright (c) 1993-1995, 1999-2004 Apple Computer, Inc.
5 * @APPLE_LICENSE_HEADER_START@
7 * The contents of this file constitute Original Code as defined in and
8 * are subject to the Apple Public Source License Version 1.1 (the
9 * "License"). You may not use this file except in compliance with the
10 * License. Please obtain a copy of the License at
11 * http://www.apple.com/publicsource and read it before using this file.
13 * This Original Code and all software distributed under the License are
14 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
18 * License for the specific language governing rights and limitations
21 * @APPLE_LICENSE_HEADER_END@
24 * Timer interrupt callout module.
28 * 20 December 2000 (debo)
32 #include <mach/mach_types.h>
34 #include <kern/clock.h>
35 #include <kern/processor.h>
37 #include <kern/timer_call.h>
38 #include <kern/call_entry.h>
40 #include <sys/kdebug.h>
42 decl_simple_lock_data(static,timer_call_lock
)
53 #define qe(x) ((queue_entry_t)(x))
54 #define TC(x) ((timer_call_t)(x))
57 timer_call_initialize(void)
61 simple_lock_init(&timer_call_lock
, 0);
64 simple_lock(&timer_call_lock
);
66 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
68 simple_unlock(&timer_call_lock
);
75 timer_call_func_t func
,
76 timer_call_param_t param0
)
78 call_entry_setup(call
, func
, param0
);
83 _delayed_call_enqueue(
89 current
= TC(queue_first(queue
));
92 if ( queue_end(queue
, qe(current
)) ||
93 call
->deadline
< current
->deadline
) {
94 current
= TC(queue_prev(qe(current
)));
98 current
= TC(queue_next(qe(current
)));
101 insque(qe(call
), qe(current
));
102 if (++timer_call_vars
.delayed_num
> timer_call_vars
.delayed_hiwat
)
103 timer_call_vars
.delayed_hiwat
= timer_call_vars
.delayed_num
;
105 call
->state
= DELAYED
;
110 _delayed_call_dequeue(
113 (void)remque(qe(call
));
114 timer_call_vars
.delayed_num
--;
121 _set_delayed_call_timer(
124 etimer_set_deadline(call
->deadline
);
132 boolean_t result
= TRUE
;
137 simple_lock(&timer_call_lock
);
139 if (call
->state
== DELAYED
)
140 _delayed_call_dequeue(call
);
145 call
->deadline
= deadline
;
147 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
149 _delayed_call_enqueue(queue
, call
);
151 if (queue_first(queue
) == qe(call
))
152 _set_delayed_call_timer(call
);
154 simple_unlock(&timer_call_lock
);
163 timer_call_param_t param1
,
166 boolean_t result
= TRUE
;
171 simple_lock(&timer_call_lock
);
173 if (call
->state
== DELAYED
)
174 _delayed_call_dequeue(call
);
178 call
->param1
= param1
;
179 call
->deadline
= deadline
;
181 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
183 _delayed_call_enqueue(queue
, call
);
185 if (queue_first(queue
) == qe(call
))
186 _set_delayed_call_timer(call
);
188 simple_unlock(&timer_call_lock
);
198 boolean_t result
= TRUE
;
202 simple_lock(&timer_call_lock
);
204 if (call
->state
== DELAYED
)
205 _delayed_call_dequeue(call
);
209 simple_unlock(&timer_call_lock
);
216 timer_call_is_delayed(
220 boolean_t result
= FALSE
;
224 simple_lock(&timer_call_lock
);
226 if (call
->state
== DELAYED
) {
227 if (deadline
!= NULL
)
228 *deadline
= call
->deadline
;
232 simple_unlock(&timer_call_lock
);
239 * Called at splclock.
244 processor_t processor
)
247 queue_t queue
, myqueue
;
249 assert(processor
!= current_processor());
251 queue
= &PROCESSOR_DATA(processor
, timer_call_queue
);
252 myqueue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
254 simple_lock(&timer_call_lock
);
256 call
= TC(queue_first(queue
));
258 while (!queue_end(queue
, qe(call
))) {
259 _delayed_call_dequeue(call
);
261 _delayed_call_enqueue(myqueue
, call
);
263 call
= TC(queue_first(queue
));
266 call
= TC(queue_first(myqueue
));
268 if (!queue_end(myqueue
, qe(call
)))
269 _set_delayed_call_timer(call
);
271 simple_unlock(&timer_call_lock
);
276 timer_call_interrupt(
282 simple_lock(&timer_call_lock
);
284 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
286 call
= TC(queue_first(queue
));
288 while (!queue_end(queue
, qe(call
))) {
290 if (call
->deadline
<= timestamp
) {
291 timer_call_func_t func
;
292 timer_call_param_t param0
, param1
;
294 _delayed_call_dequeue(call
);
297 param0
= call
->param0
;
298 param1
= call
->param1
;
300 simple_unlock(&timer_call_lock
);
302 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI
, 2) | DBG_FUNC_START
, (int)func
, param0
, param1
, 0, 0);
304 (*func
)(param0
, param1
);
306 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI
, 2) | DBG_FUNC_END
, (int)func
, param0
, param1
, 0, 0);
308 simple_lock(&timer_call_lock
);
313 call
= TC(queue_first(queue
));
316 if (!queue_end(queue
, qe(call
)))
317 _set_delayed_call_timer(call
);
319 simple_unlock(&timer_call_lock
);