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 #include <sys/kdebug.h>
50 decl_simple_lock_data(static,timer_call_lock
)
61 #define qe(x) ((queue_entry_t)(x))
62 #define TC(x) ((timer_call_t)(x))
65 timer_call_initialize(void)
69 simple_lock_init(&timer_call_lock
, 0);
72 simple_lock(&timer_call_lock
);
74 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
76 simple_unlock(&timer_call_lock
);
83 timer_call_func_t func
,
84 timer_call_param_t param0
)
86 call_entry_setup(call
, func
, param0
);
91 _delayed_call_enqueue(
97 current
= TC(queue_first(queue
));
100 if ( queue_end(queue
, qe(current
)) ||
101 call
->deadline
< current
->deadline
) {
102 current
= TC(queue_prev(qe(current
)));
106 current
= TC(queue_next(qe(current
)));
109 insque(qe(call
), qe(current
));
110 if (++timer_call_vars
.delayed_num
> timer_call_vars
.delayed_hiwat
)
111 timer_call_vars
.delayed_hiwat
= timer_call_vars
.delayed_num
;
113 call
->state
= DELAYED
;
118 _delayed_call_dequeue(
121 (void)remque(qe(call
));
122 timer_call_vars
.delayed_num
--;
129 _set_delayed_call_timer(
132 etimer_set_deadline(call
->deadline
);
140 boolean_t result
= TRUE
;
145 simple_lock(&timer_call_lock
);
147 if (call
->state
== DELAYED
)
148 _delayed_call_dequeue(call
);
153 call
->deadline
= deadline
;
155 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
157 _delayed_call_enqueue(queue
, call
);
159 if (queue_first(queue
) == qe(call
))
160 _set_delayed_call_timer(call
);
162 simple_unlock(&timer_call_lock
);
171 timer_call_param_t param1
,
174 boolean_t result
= TRUE
;
179 simple_lock(&timer_call_lock
);
181 if (call
->state
== DELAYED
)
182 _delayed_call_dequeue(call
);
186 call
->param1
= param1
;
187 call
->deadline
= deadline
;
189 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
191 _delayed_call_enqueue(queue
, call
);
193 if (queue_first(queue
) == qe(call
))
194 _set_delayed_call_timer(call
);
196 simple_unlock(&timer_call_lock
);
206 boolean_t result
= TRUE
;
210 simple_lock(&timer_call_lock
);
212 if (call
->state
== DELAYED
)
213 _delayed_call_dequeue(call
);
217 simple_unlock(&timer_call_lock
);
224 timer_call_is_delayed(
228 boolean_t result
= FALSE
;
232 simple_lock(&timer_call_lock
);
234 if (call
->state
== DELAYED
) {
235 if (deadline
!= NULL
)
236 *deadline
= call
->deadline
;
240 simple_unlock(&timer_call_lock
);
247 * Called at splclock.
252 processor_t processor
)
255 queue_t queue
, myqueue
;
257 assert(processor
!= current_processor());
259 queue
= &PROCESSOR_DATA(processor
, timer_call_queue
);
260 myqueue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
262 simple_lock(&timer_call_lock
);
264 call
= TC(queue_first(queue
));
266 while (!queue_end(queue
, qe(call
))) {
267 _delayed_call_dequeue(call
);
269 _delayed_call_enqueue(myqueue
, call
);
271 call
= TC(queue_first(queue
));
274 call
= TC(queue_first(myqueue
));
276 if (!queue_end(myqueue
, qe(call
)))
277 _set_delayed_call_timer(call
);
279 simple_unlock(&timer_call_lock
);
284 timer_call_interrupt(
290 simple_lock(&timer_call_lock
);
292 queue
= &PROCESSOR_DATA(current_processor(), timer_call_queue
);
294 call
= TC(queue_first(queue
));
296 while (!queue_end(queue
, qe(call
))) {
298 if (call
->deadline
<= timestamp
) {
299 timer_call_func_t func
;
300 timer_call_param_t param0
, param1
;
302 _delayed_call_dequeue(call
);
305 param0
= call
->param0
;
306 param1
= call
->param1
;
308 simple_unlock(&timer_call_lock
);
310 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI
, 2) | DBG_FUNC_START
, (int)func
, param0
, param1
, 0, 0);
312 (*func
)(param0
, param1
);
314 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI
, 2) | DBG_FUNC_END
, (int)func
, param0
, param1
, 0, 0);
316 simple_lock(&timer_call_lock
);
321 call
= TC(queue_first(queue
));
324 if (!queue_end(queue
, qe(call
)))
325 _set_delayed_call_timer(call
);
327 simple_unlock(&timer_call_lock
);