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>
45 * Until we arrange for per-cpu timers, use the master cpus queues only.
46 * Fortunately, the timer_call_lock synchronizes access to all queues.
49 #define cpu_number() 0
52 decl_simple_lock_data(static,timer_call_lock
)
56 timer_call_queues
[NCPUS
];
67 #define qe(x) ((queue_entry_t)(x))
68 #define TC(x) ((timer_call_t)(x))
71 timer_call_initialize(void)
76 simple_lock_init(&timer_call_lock
, ETAP_MISC_TIMER
);
79 simple_lock(&timer_call_lock
);
81 for (i
= 0; i
< NCPUS
; i
++)
82 queue_init(&timer_call_queues
[i
]);
84 clock_set_timer_func((clock_timer_func_t
)timer_call_interrupt
);
86 simple_unlock(&timer_call_lock
);
93 timer_call_func_t func
,
94 timer_call_param_t param0
)
96 call_entry_setup(call
, func
, param0
);
101 _delayed_call_enqueue(
105 timer_call_t current
;
107 current
= TC(queue_first(queue
));
110 if ( queue_end(queue
, qe(current
)) ||
111 call
->deadline
< current
->deadline
) {
112 current
= TC(queue_prev(qe(current
)));
116 current
= TC(queue_next(qe(current
)));
119 insque(qe(call
), qe(current
));
120 if (++timer_call_vars
.delayed_num
> timer_call_vars
.delayed_hiwat
)
121 timer_call_vars
.delayed_hiwat
= timer_call_vars
.delayed_num
;
123 call
->state
= DELAYED
;
128 _delayed_call_dequeue(
131 (void)remque(qe(call
));
132 timer_call_vars
.delayed_num
--;
139 _set_delayed_call_timer(
142 clock_set_timer_deadline(call
->deadline
);
150 boolean_t result
= TRUE
;
155 simple_lock(&timer_call_lock
);
157 if (call
->state
== DELAYED
)
158 _delayed_call_dequeue(call
);
163 call
->deadline
= deadline
;
165 queue
= &timer_call_queues
[cpu_number()];
167 _delayed_call_enqueue(queue
, call
);
169 if (queue_first(queue
) == qe(call
))
170 _set_delayed_call_timer(call
);
172 simple_unlock(&timer_call_lock
);
181 timer_call_param_t param1
,
184 boolean_t result
= TRUE
;
189 simple_lock(&timer_call_lock
);
191 if (call
->state
== DELAYED
)
192 _delayed_call_dequeue(call
);
196 call
->param1
= param1
;
197 call
->deadline
= deadline
;
199 queue
= &timer_call_queues
[cpu_number()];
201 _delayed_call_enqueue(queue
, call
);
203 if (queue_first(queue
) == qe(call
))
204 _set_delayed_call_timer(call
);
206 simple_unlock(&timer_call_lock
);
216 boolean_t result
= TRUE
;
220 simple_lock(&timer_call_lock
);
222 if (call
->state
== DELAYED
)
223 _delayed_call_dequeue(call
);
227 simple_unlock(&timer_call_lock
);
234 timer_call_is_delayed(
238 boolean_t result
= FALSE
;
242 simple_lock(&timer_call_lock
);
244 if (call
->state
== DELAYED
) {
245 if (deadline
!= NULL
)
246 *deadline
= call
->deadline
;
250 simple_unlock(&timer_call_lock
);
257 * Called at splclock.
262 processor_t processor
)
265 queue_t queue
, myqueue
;
267 assert(processor
!= current_processor());
269 queue
= &timer_call_queues
[processor
->slot_num
];
270 myqueue
= &timer_call_queues
[cpu_number()];
272 simple_lock(&timer_call_lock
);
274 call
= TC(queue_first(queue
));
276 while (!queue_end(queue
, qe(call
))) {
277 _delayed_call_dequeue(call
);
279 _delayed_call_enqueue(myqueue
, call
);
281 call
= TC(queue_first(queue
));
284 call
= TC(queue_first(myqueue
));
286 if (!queue_end(myqueue
, qe(call
)))
287 _set_delayed_call_timer(call
);
289 simple_unlock(&timer_call_lock
);
294 timer_call_interrupt(
298 queue_t queue
= &timer_call_queues
[cpu_number()];
300 simple_lock(&timer_call_lock
);
302 call
= TC(queue_first(queue
));
304 while (!queue_end(queue
, qe(call
))) {
305 if (call
->deadline
<= timestamp
) {
306 timer_call_func_t func
;
307 timer_call_param_t param0
, param1
;
309 _delayed_call_dequeue(call
);
312 param0
= call
->param0
;
313 param1
= call
->param1
;
315 simple_unlock(&timer_call_lock
);
317 (*func
)(param0
, param1
);
319 simple_lock(&timer_call_lock
);
324 call
= TC(queue_first(queue
));
327 if (!queue_end(queue
, qe(call
)))
328 _set_delayed_call_timer(call
);
330 simple_unlock(&timer_call_lock
);