2 * Copyright (c) 1993-1995, 1999-2004 Apple Computer, Inc.
5 * @APPLE_LICENSE_OSREFERENCE_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
11 * License may not be used to create, or enable the creation or
12 * redistribution of, unlawful or unlicensed copies of an Apple operating
13 * system, or to circumvent, violate, or enable the circumvention or
14 * violation of, any terms of an Apple operating system software license
17 * Please obtain a copy of the License at
18 * http://www.opensource.apple.com/apsl/ and read it before using this
21 * The Original Code and all software distributed under the License are
22 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
23 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
24 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
26 * Please see the License for the specific language governing rights and
27 * limitations under the License.
29 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
32 * Timer interrupt callout module.
36 * 20 December 2000 (debo)
40 #include <mach/mach_types.h>
42 #include <kern/clock.h>
43 #include <kern/processor.h>
45 #include <kern/timer_call.h>
46 #include <kern/call_entry.h>
48 decl_simple_lock_data(static,timer_call_lock
)
59 #define qe(x) ((queue_entry_t)(x))
60 #define TC(x) ((timer_call_t)(x))
63 timer_call_initialize(void)
67 simple_lock_init(&timer_call_lock
, 0);
70 simple_lock(&timer_call_lock
);
72 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
74 simple_unlock(&timer_call_lock
);
81 timer_call_func_t func
,
82 timer_call_param_t param0
)
84 call_entry_setup(call
, func
, param0
);
89 _delayed_call_enqueue(
95 current
= TC(queue_first(queue
));
98 if ( queue_end(queue
, qe(current
)) ||
99 call
->deadline
< current
->deadline
) {
100 current
= TC(queue_prev(qe(current
)));
104 current
= TC(queue_next(qe(current
)));
107 insque(qe(call
), qe(current
));
108 if (++timer_call_vars
.delayed_num
> timer_call_vars
.delayed_hiwat
)
109 timer_call_vars
.delayed_hiwat
= timer_call_vars
.delayed_num
;
111 call
->state
= DELAYED
;
116 _delayed_call_dequeue(
119 (void)remque(qe(call
));
120 timer_call_vars
.delayed_num
--;
127 _set_delayed_call_timer(
130 clock_set_timer_deadline(call
->deadline
);
138 boolean_t result
= TRUE
;
143 simple_lock(&timer_call_lock
);
145 if (call
->state
== DELAYED
)
146 _delayed_call_dequeue(call
);
151 call
->deadline
= deadline
;
153 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
155 _delayed_call_enqueue(queue
, call
);
157 if (queue_first(queue
) == qe(call
))
158 _set_delayed_call_timer(call
);
160 simple_unlock(&timer_call_lock
);
169 timer_call_param_t param1
,
172 boolean_t result
= TRUE
;
177 simple_lock(&timer_call_lock
);
179 if (call
->state
== DELAYED
)
180 _delayed_call_dequeue(call
);
184 call
->param1
= param1
;
185 call
->deadline
= deadline
;
187 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
189 _delayed_call_enqueue(queue
, call
);
191 if (queue_first(queue
) == qe(call
))
192 _set_delayed_call_timer(call
);
194 simple_unlock(&timer_call_lock
);
204 boolean_t result
= TRUE
;
208 simple_lock(&timer_call_lock
);
210 if (call
->state
== DELAYED
)
211 _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
);
282 timer_call_interrupt(
288 simple_lock(&timer_call_lock
);
290 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
292 call
= TC(queue_first(queue
));
294 while (!queue_end(queue
, qe(call
))) {
295 if (call
->deadline
<= timestamp
) {
296 timer_call_func_t func
;
297 timer_call_param_t param0
, param1
;
299 _delayed_call_dequeue(call
);
302 param0
= call
->param0
;
303 param1
= call
->param1
;
305 simple_unlock(&timer_call_lock
);
307 (*func
)(param0
, param1
);
309 simple_lock(&timer_call_lock
);
314 call
= TC(queue_first(queue
));
317 if (!queue_end(queue
, qe(call
)))
318 _set_delayed_call_timer(call
);
320 simple_unlock(&timer_call_lock
);