2 * Copyright (c) 1993-1995, 1999-2000 Apple Computer, Inc.
5 * @APPLE_LICENSE_HEADER_START@
7 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
9 * This file contains Original Code and/or Modifications of Original Code
10 * as defined in and that are subject to the Apple Public Source License
11 * Version 2.0 (the 'License'). You may not use this file except in
12 * compliance with the License. Please obtain a copy of the License at
13 * http://www.opensource.apple.com/apsl/ and read it before using this
16 * The Original Code and all software distributed under the License are
17 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
18 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
19 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
21 * Please see the License for the specific language governing rights and
22 * limitations under the License.
24 * @APPLE_LICENSE_HEADER_END@
27 * Timer interrupt callout module.
31 * 20 December 2000 (debo)
35 #include <mach/mach_types.h>
37 #include <kern/clock.h>
38 #include <kern/processor.h>
40 #include <kern/timer_call.h>
41 #include <kern/call_entry.h>
43 decl_simple_lock_data(static,timer_call_lock
)
47 delayed_call_queues
[NCPUS
];
55 timer_call_initialized
= FALSE
;
61 #define qe(x) ((queue_entry_t)(x))
62 #define TC(x) ((timer_call_t)(x))
65 timer_call_initialize(void)
70 if (timer_call_initialized
)
71 panic("timer_call_initialize");
73 simple_lock_init(&timer_call_lock
, ETAP_MISC_TIMER
);
76 simple_lock(&timer_call_lock
);
78 for (i
= 0; i
< NCPUS
; i
++)
79 queue_init(&delayed_call_queues
[i
]);
81 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
83 timer_call_initialized
= TRUE
;
85 simple_unlock(&timer_call_lock
);
92 timer_call_func_t func
,
93 timer_call_param_t param0
)
95 call_entry_setup(call
, func
, param0
);
100 _delayed_call_enqueue(
104 timer_call_t current
;
106 current
= TC(queue_first(queue
));
109 if ( queue_end(queue
, qe(current
)) ||
110 call
->deadline
< current
->deadline
) {
111 current
= TC(queue_prev(qe(current
)));
115 current
= TC(queue_next(qe(current
)));
118 insque(qe(call
), qe(current
));
119 if (++timer_calls
.delayed_num
> timer_calls
.delayed_hiwat
)
120 timer_calls
.delayed_hiwat
= timer_calls
.delayed_num
;
122 call
->state
= DELAYED
;
127 _delayed_call_dequeue(
130 (void)remque(qe(call
));
131 timer_calls
.delayed_num
--;
138 _set_delayed_call_timer(
141 clock_set_timer_deadline(call
->deadline
);
149 boolean_t result
= TRUE
;
154 simple_lock(&timer_call_lock
);
156 if (call
->state
== DELAYED
)
157 _delayed_call_dequeue(call
);
162 call
->deadline
= deadline
;
164 delayed
= &delayed_call_queues
[cpu_number()];
166 _delayed_call_enqueue(delayed
, call
);
168 if (queue_first(delayed
) == qe(call
))
169 _set_delayed_call_timer(call
);
171 simple_unlock(&timer_call_lock
);
180 timer_call_param_t param1
,
183 boolean_t result
= TRUE
;
188 simple_lock(&timer_call_lock
);
190 if (call
->state
== DELAYED
)
191 _delayed_call_dequeue(call
);
195 call
->param1
= param1
;
196 call
->deadline
= deadline
;
198 delayed
= &delayed_call_queues
[cpu_number()];
200 _delayed_call_enqueue(delayed
, call
);
202 if (queue_first(delayed
) == qe(call
))
203 _set_delayed_call_timer(call
);
205 simple_unlock(&timer_call_lock
);
215 boolean_t result
= TRUE
;
219 simple_lock(&timer_call_lock
);
221 if (call
->state
== DELAYED
)
222 _delayed_call_dequeue(call
);
226 simple_unlock(&timer_call_lock
);
233 timer_call_is_delayed(
237 boolean_t result
= FALSE
;
241 simple_lock(&timer_call_lock
);
243 if (call
->state
== DELAYED
) {
244 if (deadline
!= NULL
)
245 *deadline
= call
->deadline
;
249 simple_unlock(&timer_call_lock
);
256 * Called at splclock.
261 processor_t processor
)
264 queue_t delayed
, delayed1
;
266 assert(processor
!= current_processor());
268 delayed
= &delayed_call_queues
[processor
->slot_num
];
269 delayed1
= &delayed_call_queues
[cpu_number()];
271 simple_lock(&timer_call_lock
);
273 call
= TC(queue_first(delayed
));
275 while (!queue_end(delayed
, qe(call
))) {
276 _delayed_call_dequeue(call
);
278 _delayed_call_enqueue(delayed1
, call
);
280 call
= TC(queue_first(delayed
));
283 call
= TC(queue_first(delayed1
));
285 if (!queue_end(delayed1
, qe(call
)))
286 _set_delayed_call_timer(call
);
288 simple_unlock(&timer_call_lock
);
293 timer_call_interrupt(
297 queue_t delayed
= &delayed_call_queues
[cpu_number()];
299 simple_lock(&timer_call_lock
);
301 call
= TC(queue_first(delayed
));
303 while (!queue_end(delayed
, qe(call
))) {
304 if (call
->deadline
<= timestamp
) {
305 timer_call_func_t func
;
306 timer_call_param_t param0
, param1
;
308 _delayed_call_dequeue(call
);
311 param0
= call
->param0
;
312 param1
= call
->param1
;
314 simple_unlock(&timer_call_lock
);
316 (*func
)(param0
, param1
);
318 simple_lock(&timer_call_lock
);
323 call
= TC(queue_first(delayed
));
326 if (!queue_end(delayed
, qe(call
)))
327 _set_delayed_call_timer(call
);
329 simple_unlock(&timer_call_lock
);