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>
42 * Until we arrange for per-cpu timers, use the master cpus queues only.
43 * Fortunately, the timer_call_lock synchronizes access to all queues.
46 #define cpu_number() 0
49 decl_simple_lock_data(static,timer_call_lock
)
53 timer_call_queues
[NCPUS
];
64 #define qe(x) ((queue_entry_t)(x))
65 #define TC(x) ((timer_call_t)(x))
68 timer_call_initialize(void)
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(&timer_call_queues
[i
]);
81 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
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_call_vars
.delayed_num
> timer_call_vars
.delayed_hiwat
)
118 timer_call_vars
.delayed_hiwat
= timer_call_vars
.delayed_num
;
120 call
->state
= DELAYED
;
125 _delayed_call_dequeue(
128 (void)remque(qe(call
));
129 timer_call_vars
.delayed_num
--;
136 _set_delayed_call_timer(
139 clock_set_timer_deadline(call
->deadline
);
147 boolean_t result
= TRUE
;
152 simple_lock(&timer_call_lock
);
154 if (call
->state
== DELAYED
)
155 _delayed_call_dequeue(call
);
160 call
->deadline
= deadline
;
162 queue
= &timer_call_queues
[cpu_number()];
164 _delayed_call_enqueue(queue
, call
);
166 if (queue_first(queue
) == qe(call
))
167 _set_delayed_call_timer(call
);
169 simple_unlock(&timer_call_lock
);
178 timer_call_param_t param1
,
181 boolean_t result
= TRUE
;
186 simple_lock(&timer_call_lock
);
188 if (call
->state
== DELAYED
)
189 _delayed_call_dequeue(call
);
193 call
->param1
= param1
;
194 call
->deadline
= deadline
;
196 queue
= &timer_call_queues
[cpu_number()];
198 _delayed_call_enqueue(queue
, call
);
200 if (queue_first(queue
) == qe(call
))
201 _set_delayed_call_timer(call
);
203 simple_unlock(&timer_call_lock
);
213 boolean_t result
= TRUE
;
217 simple_lock(&timer_call_lock
);
219 if (call
->state
== DELAYED
)
220 _delayed_call_dequeue(call
);
224 simple_unlock(&timer_call_lock
);
231 timer_call_is_delayed(
235 boolean_t result
= FALSE
;
239 simple_lock(&timer_call_lock
);
241 if (call
->state
== DELAYED
) {
242 if (deadline
!= NULL
)
243 *deadline
= call
->deadline
;
247 simple_unlock(&timer_call_lock
);
254 * Called at splclock.
259 processor_t processor
)
262 queue_t queue
, myqueue
;
264 assert(processor
!= current_processor());
266 queue
= &timer_call_queues
[processor
->slot_num
];
267 myqueue
= &timer_call_queues
[cpu_number()];
269 simple_lock(&timer_call_lock
);
271 call
= TC(queue_first(queue
));
273 while (!queue_end(queue
, qe(call
))) {
274 _delayed_call_dequeue(call
);
276 _delayed_call_enqueue(myqueue
, call
);
278 call
= TC(queue_first(queue
));
281 call
= TC(queue_first(myqueue
));
283 if (!queue_end(myqueue
, qe(call
)))
284 _set_delayed_call_timer(call
);
286 simple_unlock(&timer_call_lock
);
291 timer_call_interrupt(
295 queue_t queue
= &timer_call_queues
[cpu_number()];
297 simple_lock(&timer_call_lock
);
299 call
= TC(queue_first(queue
));
301 while (!queue_end(queue
, qe(call
))) {
302 if (call
->deadline
<= timestamp
) {
303 timer_call_func_t func
;
304 timer_call_param_t param0
, param1
;
306 _delayed_call_dequeue(call
);
309 param0
= call
->param0
;
310 param1
= call
->param1
;
312 simple_unlock(&timer_call_lock
);
314 (*func
)(param0
, param1
);
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
);