2 * Copyright (c) 1993-1995, 1999-2000 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>
36 #include <kern/timer_call.h>
37 #include <kern/call_entry.h>
39 decl_simple_lock_data(static,timer_call_lock
)
43 delayed_call_queues
[NCPUS
];
53 timer_call_initialized
= FALSE
;
59 #define qe(x) ((queue_entry_t)(x))
60 #define TC(x) ((timer_call_t)(x))
63 timer_call_initialize(void)
68 if (timer_call_initialized
)
69 panic("timer_call_initialize");
71 simple_lock_init(&timer_call_lock
, ETAP_MISC_TIMER
);
74 simple_lock(&timer_call_lock
);
76 for (i
= 0; i
< NCPUS
; i
++)
77 queue_init(&delayed_call_queues
[i
]);
79 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
81 timer_call_initialized
= TRUE
;
83 simple_unlock(&timer_call_lock
);
90 timer_call_func_t func
,
91 timer_call_param_t param0
)
93 call_entry_setup(call
, func
, param0
);
98 _delayed_call_enqueue(
102 timer_call_t current
;
104 current
= TC(queue_first(queue
));
107 if ( queue_end(queue
, qe(current
)) ||
108 call
->deadline
< current
->deadline
) {
109 current
= TC(queue_prev(qe(current
)));
113 current
= TC(queue_next(qe(current
)));
116 insque(qe(call
), qe(current
));
117 if (++timer_calls
.delayed_num
> timer_calls
.delayed_hiwat
)
118 timer_calls
.delayed_hiwat
= timer_calls
.delayed_num
;
120 call
->state
= DELAYED
;
125 _delayed_call_dequeue(
128 (void)remque(qe(call
));
129 timer_calls
.delayed_num
--;
136 _pending_call_enqueue(
140 enqueue_tail(queue
, qe(call
));
141 if (++timer_calls
.pending_num
> timer_calls
.pending_hiwat
)
142 timer_calls
.pending_hiwat
= timer_calls
.pending_num
;
144 call
->state
= PENDING
;
149 _pending_call_dequeue(
152 (void)remque(qe(call
));
153 timer_calls
.pending_num
--;
160 _set_delayed_call_timer(
163 clock_set_timer_deadline(call
->deadline
);
171 boolean_t result
= TRUE
;
176 simple_lock(&timer_call_lock
);
178 if (call
->state
== PENDING
)
179 _pending_call_dequeue(call
);
180 else if (call
->state
== DELAYED
)
181 _delayed_call_dequeue(call
);
182 else if (call
->state
== IDLE
)
186 call
->deadline
= deadline
;
188 delayed
= &delayed_call_queues
[cpu_number()];
190 _delayed_call_enqueue(delayed
, call
);
192 if (queue_first(delayed
) == qe(call
))
193 _set_delayed_call_timer(call
);
195 simple_unlock(&timer_call_lock
);
204 timer_call_param_t param1
,
207 boolean_t result
= TRUE
;
212 simple_lock(&timer_call_lock
);
214 if (call
->state
== PENDING
)
215 _pending_call_dequeue(call
);
216 else if (call
->state
== DELAYED
)
217 _delayed_call_dequeue(call
);
218 else if (call
->state
== IDLE
)
221 call
->param1
= param1
;
222 call
->deadline
= deadline
;
224 delayed
= &delayed_call_queues
[cpu_number()];
226 _delayed_call_enqueue(delayed
, call
);
228 if (queue_first(delayed
) == qe(call
))
229 _set_delayed_call_timer(call
);
231 simple_unlock(&timer_call_lock
);
241 boolean_t result
= TRUE
;
245 simple_lock(&timer_call_lock
);
247 if (call
->state
== PENDING
)
248 _pending_call_dequeue(call
);
249 else if (call
->state
== DELAYED
)
250 _delayed_call_dequeue(call
);
254 simple_unlock(&timer_call_lock
);
261 timer_call_is_delayed(
265 boolean_t result
= FALSE
;
269 simple_lock(&timer_call_lock
);
271 if (call
->state
== DELAYED
) {
272 if (deadline
!= NULL
)
273 *deadline
= call
->deadline
;
277 simple_unlock(&timer_call_lock
);
285 timer_call_interrupt(
289 queue_t delayed
= &delayed_call_queues
[cpu_number()];
291 simple_lock(&timer_call_lock
);
293 call
= TC(queue_first(delayed
));
295 while (!queue_end(delayed
, qe(call
))) {
296 if (call
->deadline
<= timestamp
) {
297 timer_call_func_t func
;
298 timer_call_param_t param0
, param1
;
300 _delayed_call_dequeue(call
);
303 param0
= call
->param0
;
304 param1
= call
->param1
;
306 simple_unlock(&timer_call_lock
);
308 (*func
)(param0
, param1
);
310 simple_lock(&timer_call_lock
);
315 call
= TC(queue_first(delayed
));
318 if (!queue_end(delayed
, qe(call
)))
319 _set_delayed_call_timer(call
);
321 simple_unlock(&timer_call_lock
);