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
;
57 AbsoluteTime timestamp
);
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 CMP_ABSOLUTETIME(&call
->deadline
,
109 ¤t
->deadline
) < 0 ) {
110 current
= TC(queue_prev(qe(current
)));
114 current
= TC(queue_next(qe(current
)));
117 insque(qe(call
), qe(current
));
118 if (++timer_calls
.delayed_num
> timer_calls
.delayed_hiwat
)
119 timer_calls
.delayed_hiwat
= timer_calls
.delayed_num
;
121 call
->state
= DELAYED
;
126 _delayed_call_dequeue(
129 (void)remque(qe(call
));
130 timer_calls
.delayed_num
--;
137 _pending_call_enqueue(
141 enqueue_tail(queue
, qe(call
));
142 if (++timer_calls
.pending_num
> timer_calls
.pending_hiwat
)
143 timer_calls
.pending_hiwat
= timer_calls
.pending_num
;
145 call
->state
= PENDING
;
150 _pending_call_dequeue(
153 (void)remque(qe(call
));
154 timer_calls
.pending_num
--;
161 _set_delayed_call_timer(
164 clock_set_timer_deadline(call
->deadline
);
170 AbsoluteTime deadline
)
172 boolean_t result
= TRUE
;
177 simple_lock(&timer_call_lock
);
179 if (call
->state
== PENDING
)
180 _pending_call_dequeue(call
);
181 else if (call
->state
== DELAYED
)
182 _delayed_call_dequeue(call
);
183 else if (call
->state
== IDLE
)
187 call
->deadline
= deadline
;
189 delayed
= &delayed_call_queues
[cpu_number()];
191 _delayed_call_enqueue(delayed
, call
);
193 if (queue_first(delayed
) == qe(call
))
194 _set_delayed_call_timer(call
);
196 simple_unlock(&timer_call_lock
);
205 timer_call_param_t param1
,
206 AbsoluteTime deadline
)
208 boolean_t result
= TRUE
;
213 simple_lock(&timer_call_lock
);
215 if (call
->state
== PENDING
)
216 _pending_call_dequeue(call
);
217 else if (call
->state
== DELAYED
)
218 _delayed_call_dequeue(call
);
219 else if (call
->state
== IDLE
)
222 call
->param1
= param1
;
223 call
->deadline
= deadline
;
225 delayed
= &delayed_call_queues
[cpu_number()];
227 _delayed_call_enqueue(delayed
, call
);
229 if (queue_first(delayed
) == qe(call
))
230 _set_delayed_call_timer(call
);
232 simple_unlock(&timer_call_lock
);
242 boolean_t result
= TRUE
;
246 simple_lock(&timer_call_lock
);
248 if (call
->state
== PENDING
)
249 _pending_call_dequeue(call
);
250 else if (call
->state
== DELAYED
)
251 _delayed_call_dequeue(call
);
255 simple_unlock(&timer_call_lock
);
262 timer_call_is_delayed(
264 AbsoluteTime
*deadline
)
266 boolean_t result
= FALSE
;
270 simple_lock(&timer_call_lock
);
272 if (call
->state
== DELAYED
) {
273 if (deadline
!= NULL
)
274 *deadline
= call
->deadline
;
278 simple_unlock(&timer_call_lock
);
286 timer_call_interrupt(
287 AbsoluteTime timestamp
)
290 queue_t delayed
= &delayed_call_queues
[cpu_number()];
292 simple_lock(&timer_call_lock
);
294 call
= TC(queue_first(delayed
));
296 while (!queue_end(delayed
, qe(call
))) {
297 if (CMP_ABSOLUTETIME(&call
->deadline
, ×tamp
) <= 0) {
298 timer_call_func_t func
;
299 timer_call_param_t param0
, param1
;
301 _delayed_call_dequeue(call
);
304 param0
= call
->param0
;
305 param1
= call
->param1
;
307 simple_unlock(&timer_call_lock
);
309 (*func
)(param0
, param1
);
311 simple_lock(&timer_call_lock
);
316 call
= TC(queue_first(delayed
));
319 if (!queue_end(delayed
, qe(call
)))
320 _set_delayed_call_timer(call
);
322 simple_unlock(&timer_call_lock
);