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>
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
)
44 delayed_call_queues
[NCPUS
];
52 timer_call_initialized
= FALSE
;
58 #define qe(x) ((queue_entry_t)(x))
59 #define TC(x) ((timer_call_t)(x))
62 timer_call_initialize(void)
67 if (timer_call_initialized
)
68 panic("timer_call_initialize");
70 simple_lock_init(&timer_call_lock
, ETAP_MISC_TIMER
);
73 simple_lock(&timer_call_lock
);
75 for (i
= 0; i
< NCPUS
; i
++)
76 queue_init(&delayed_call_queues
[i
]);
78 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
80 timer_call_initialized
= TRUE
;
82 simple_unlock(&timer_call_lock
);
89 timer_call_func_t func
,
90 timer_call_param_t param0
)
92 call_entry_setup(call
, func
, param0
);
97 _delayed_call_enqueue(
101 timer_call_t current
;
103 current
= TC(queue_first(queue
));
106 if ( queue_end(queue
, qe(current
)) ||
107 call
->deadline
< current
->deadline
) {
108 current
= TC(queue_prev(qe(current
)));
112 current
= TC(queue_next(qe(current
)));
115 insque(qe(call
), qe(current
));
116 if (++timer_calls
.delayed_num
> timer_calls
.delayed_hiwat
)
117 timer_calls
.delayed_hiwat
= timer_calls
.delayed_num
;
119 call
->state
= DELAYED
;
124 _delayed_call_dequeue(
127 (void)remque(qe(call
));
128 timer_calls
.delayed_num
--;
135 _set_delayed_call_timer(
138 clock_set_timer_deadline(call
->deadline
);
146 boolean_t result
= TRUE
;
151 simple_lock(&timer_call_lock
);
153 if (call
->state
== DELAYED
)
154 _delayed_call_dequeue(call
);
159 call
->deadline
= deadline
;
161 delayed
= &delayed_call_queues
[cpu_number()];
163 _delayed_call_enqueue(delayed
, call
);
165 if (queue_first(delayed
) == qe(call
))
166 _set_delayed_call_timer(call
);
168 simple_unlock(&timer_call_lock
);
177 timer_call_param_t param1
,
180 boolean_t result
= TRUE
;
185 simple_lock(&timer_call_lock
);
187 if (call
->state
== DELAYED
)
188 _delayed_call_dequeue(call
);
192 call
->param1
= param1
;
193 call
->deadline
= deadline
;
195 delayed
= &delayed_call_queues
[cpu_number()];
197 _delayed_call_enqueue(delayed
, call
);
199 if (queue_first(delayed
) == qe(call
))
200 _set_delayed_call_timer(call
);
202 simple_unlock(&timer_call_lock
);
212 boolean_t result
= TRUE
;
216 simple_lock(&timer_call_lock
);
218 if (call
->state
== DELAYED
)
219 _delayed_call_dequeue(call
);
223 simple_unlock(&timer_call_lock
);
230 timer_call_is_delayed(
234 boolean_t result
= FALSE
;
238 simple_lock(&timer_call_lock
);
240 if (call
->state
== DELAYED
) {
241 if (deadline
!= NULL
)
242 *deadline
= call
->deadline
;
246 simple_unlock(&timer_call_lock
);
253 * Called at splclock.
258 processor_t processor
)
261 queue_t delayed
, delayed1
;
263 assert(processor
!= current_processor());
265 delayed
= &delayed_call_queues
[processor
->slot_num
];
266 delayed1
= &delayed_call_queues
[cpu_number()];
268 simple_lock(&timer_call_lock
);
270 call
= TC(queue_first(delayed
));
272 while (!queue_end(delayed
, qe(call
))) {
273 _delayed_call_dequeue(call
);
275 _delayed_call_enqueue(delayed1
, call
);
277 call
= TC(queue_first(delayed
));
280 call
= TC(queue_first(delayed1
));
282 if (!queue_end(delayed1
, qe(call
)))
283 _set_delayed_call_timer(call
);
285 simple_unlock(&timer_call_lock
);
290 timer_call_interrupt(
294 queue_t delayed
= &delayed_call_queues
[cpu_number()];
296 simple_lock(&timer_call_lock
);
298 call
= TC(queue_first(delayed
));
300 while (!queue_end(delayed
, qe(call
))) {
301 if (call
->deadline
<= timestamp
) {
302 timer_call_func_t func
;
303 timer_call_param_t param0
, param1
;
305 _delayed_call_dequeue(call
);
308 param0
= call
->param0
;
309 param1
= call
->param1
;
311 simple_unlock(&timer_call_lock
);
313 (*func
)(param0
, param1
);
315 simple_lock(&timer_call_lock
);
320 call
= TC(queue_first(delayed
));
323 if (!queue_end(delayed
, qe(call
)))
324 _set_delayed_call_timer(call
);
326 simple_unlock(&timer_call_lock
);