2 * Copyright (c) 1993-1995, 1999-2004 Apple Computer, Inc.
5 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. The rights granted to you under the License
11 * may not be used to create, or enable the creation or redistribution of,
12 * unlawful or unlicensed copies of an Apple operating system, or to
13 * circumvent, violate, or enable the circumvention or violation of, any
14 * terms of an Apple operating system software license agreement.
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this file.
19 * The Original Code and all software distributed under the License are
20 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
21 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
22 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
24 * Please see the License for the specific language governing rights and
25 * limitations under the License.
27 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * Timer interrupt callout module.
34 * 20 December 2000 (debo)
38 #include <mach/mach_types.h>
40 #include <kern/clock.h>
41 #include <kern/processor.h>
43 #include <kern/timer_call.h>
44 #include <kern/call_entry.h>
46 decl_simple_lock_data(static,timer_call_lock
)
57 #define qe(x) ((queue_entry_t)(x))
58 #define TC(x) ((timer_call_t)(x))
61 timer_call_initialize(void)
65 simple_lock_init(&timer_call_lock
, 0);
68 simple_lock(&timer_call_lock
);
70 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
72 simple_unlock(&timer_call_lock
);
79 timer_call_func_t func
,
80 timer_call_param_t param0
)
82 call_entry_setup(call
, func
, param0
);
87 _delayed_call_enqueue(
93 current
= TC(queue_first(queue
));
96 if ( queue_end(queue
, qe(current
)) ||
97 call
->deadline
< current
->deadline
) {
98 current
= TC(queue_prev(qe(current
)));
102 current
= TC(queue_next(qe(current
)));
105 insque(qe(call
), qe(current
));
106 if (++timer_call_vars
.delayed_num
> timer_call_vars
.delayed_hiwat
)
107 timer_call_vars
.delayed_hiwat
= timer_call_vars
.delayed_num
;
109 call
->state
= DELAYED
;
114 _delayed_call_dequeue(
117 (void)remque(qe(call
));
118 timer_call_vars
.delayed_num
--;
125 _set_delayed_call_timer(
128 clock_set_timer_deadline(call
->deadline
);
136 boolean_t result
= TRUE
;
141 simple_lock(&timer_call_lock
);
143 if (call
->state
== DELAYED
)
144 _delayed_call_dequeue(call
);
149 call
->deadline
= deadline
;
151 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
153 _delayed_call_enqueue(queue
, call
);
155 if (queue_first(queue
) == qe(call
))
156 _set_delayed_call_timer(call
);
158 simple_unlock(&timer_call_lock
);
167 timer_call_param_t param1
,
170 boolean_t result
= TRUE
;
175 simple_lock(&timer_call_lock
);
177 if (call
->state
== DELAYED
)
178 _delayed_call_dequeue(call
);
182 call
->param1
= param1
;
183 call
->deadline
= deadline
;
185 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
187 _delayed_call_enqueue(queue
, call
);
189 if (queue_first(queue
) == qe(call
))
190 _set_delayed_call_timer(call
);
192 simple_unlock(&timer_call_lock
);
202 boolean_t result
= TRUE
;
206 simple_lock(&timer_call_lock
);
208 if (call
->state
== DELAYED
)
209 _delayed_call_dequeue(call
);
213 simple_unlock(&timer_call_lock
);
220 timer_call_is_delayed(
224 boolean_t result
= FALSE
;
228 simple_lock(&timer_call_lock
);
230 if (call
->state
== DELAYED
) {
231 if (deadline
!= NULL
)
232 *deadline
= call
->deadline
;
236 simple_unlock(&timer_call_lock
);
243 * Called at splclock.
248 processor_t processor
)
251 queue_t queue
, myqueue
;
253 assert(processor
!= current_processor());
255 queue
= &PROCESSOR_DATA(processor
, timer_call_queue
);
256 myqueue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
258 simple_lock(&timer_call_lock
);
260 call
= TC(queue_first(queue
));
262 while (!queue_end(queue
, qe(call
))) {
263 _delayed_call_dequeue(call
);
265 _delayed_call_enqueue(myqueue
, call
);
267 call
= TC(queue_first(queue
));
270 call
= TC(queue_first(myqueue
));
272 if (!queue_end(myqueue
, qe(call
)))
273 _set_delayed_call_timer(call
);
275 simple_unlock(&timer_call_lock
);
280 timer_call_interrupt(
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 (*func
)(param0
, param1
);
307 simple_lock(&timer_call_lock
);
312 call
= TC(queue_first(queue
));
315 if (!queue_end(queue
, qe(call
)))
316 _set_delayed_call_timer(call
);
318 simple_unlock(&timer_call_lock
);