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 decl_simple_lock_data(static,timer_call_lock
)
51 #define qe(x) ((queue_entry_t)(x))
52 #define TC(x) ((timer_call_t)(x))
55 timer_call_initialize(void)
59 simple_lock_init(&timer_call_lock
, 0);
62 simple_lock(&timer_call_lock
);
64 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
66 simple_unlock(&timer_call_lock
);
73 timer_call_func_t func
,
74 timer_call_param_t param0
)
76 call_entry_setup(call
, func
, param0
);
81 _delayed_call_enqueue(
87 current
= TC(queue_first(queue
));
90 if ( queue_end(queue
, qe(current
)) ||
91 call
->deadline
< current
->deadline
) {
92 current
= TC(queue_prev(qe(current
)));
96 current
= TC(queue_next(qe(current
)));
99 insque(qe(call
), qe(current
));
100 if (++timer_call_vars
.delayed_num
> timer_call_vars
.delayed_hiwat
)
101 timer_call_vars
.delayed_hiwat
= timer_call_vars
.delayed_num
;
103 call
->state
= DELAYED
;
108 _delayed_call_dequeue(
111 (void)remque(qe(call
));
112 timer_call_vars
.delayed_num
--;
119 _set_delayed_call_timer(
122 clock_set_timer_deadline(call
->deadline
);
130 boolean_t result
= TRUE
;
135 simple_lock(&timer_call_lock
);
137 if (call
->state
== DELAYED
)
138 _delayed_call_dequeue(call
);
143 call
->deadline
= deadline
;
145 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
147 _delayed_call_enqueue(queue
, call
);
149 if (queue_first(queue
) == qe(call
))
150 _set_delayed_call_timer(call
);
152 simple_unlock(&timer_call_lock
);
161 timer_call_param_t param1
,
164 boolean_t result
= TRUE
;
169 simple_lock(&timer_call_lock
);
171 if (call
->state
== DELAYED
)
172 _delayed_call_dequeue(call
);
176 call
->param1
= param1
;
177 call
->deadline
= deadline
;
179 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
181 _delayed_call_enqueue(queue
, call
);
183 if (queue_first(queue
) == qe(call
))
184 _set_delayed_call_timer(call
);
186 simple_unlock(&timer_call_lock
);
196 boolean_t result
= TRUE
;
200 simple_lock(&timer_call_lock
);
202 if (call
->state
== DELAYED
)
203 _delayed_call_dequeue(call
);
207 simple_unlock(&timer_call_lock
);
214 timer_call_is_delayed(
218 boolean_t result
= FALSE
;
222 simple_lock(&timer_call_lock
);
224 if (call
->state
== DELAYED
) {
225 if (deadline
!= NULL
)
226 *deadline
= call
->deadline
;
230 simple_unlock(&timer_call_lock
);
237 * Called at splclock.
242 processor_t processor
)
245 queue_t queue
, myqueue
;
247 assert(processor
!= current_processor());
249 queue
= &PROCESSOR_DATA(processor
, timer_call_queue
);
250 myqueue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
252 simple_lock(&timer_call_lock
);
254 call
= TC(queue_first(queue
));
256 while (!queue_end(queue
, qe(call
))) {
257 _delayed_call_dequeue(call
);
259 _delayed_call_enqueue(myqueue
, call
);
261 call
= TC(queue_first(queue
));
264 call
= TC(queue_first(myqueue
));
266 if (!queue_end(myqueue
, qe(call
)))
267 _set_delayed_call_timer(call
);
269 simple_unlock(&timer_call_lock
);
274 timer_call_interrupt(
280 simple_lock(&timer_call_lock
);
282 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
284 call
= TC(queue_first(queue
));
286 while (!queue_end(queue
, qe(call
))) {
287 if (call
->deadline
<= timestamp
) {
288 timer_call_func_t func
;
289 timer_call_param_t param0
, param1
;
291 _delayed_call_dequeue(call
);
294 param0
= call
->param0
;
295 param1
= call
->param1
;
297 simple_unlock(&timer_call_lock
);
299 (*func
)(param0
, param1
);
301 simple_lock(&timer_call_lock
);
306 call
= TC(queue_first(queue
));
309 if (!queue_end(queue
, qe(call
)))
310 _set_delayed_call_timer(call
);
312 simple_unlock(&timer_call_lock
);