]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/timer_call.c
xnu-792.17.14.tar.gz
[apple/xnu.git] / osfmk / kern / timer_call.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 1993-1995, 1999-2004 Apple Computer, Inc.
1c79356b
A
3 * All rights reserved.
4 *
8f6c56a5 5 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 6 *
8f6c56a5
A
7 * This file contains Original Code and/or Modifications of Original Code
8 * as defined in and that are subject to the Apple Public Source License
9 * Version 2.0 (the 'License'). You may not use this file except in
10 * compliance with the License. The rights granted to you under the License
11 * may not be used to create, or enable the creation or redistribution of,
12 * unlawful or unlicensed copies of an Apple operating system, or to
13 * circumvent, violate, or enable the circumvention or violation of, any
14 * terms of an Apple operating system software license agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 *
19 * The Original Code and all software distributed under the License are
20 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
21 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
22 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
24 * Please see the License for the specific language governing rights and
8ad349bb 25 * limitations under the License.
8f6c56a5
A
26 *
27 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
28 */
29/*
30 * Timer interrupt callout module.
31 *
32 * HISTORY
33 *
34 * 20 December 2000 (debo)
35 * Created.
36 */
37
38#include <mach/mach_types.h>
39
40#include <kern/clock.h>
9bccf70c 41#include <kern/processor.h>
1c79356b
A
42
43#include <kern/timer_call.h>
44#include <kern/call_entry.h>
45
46decl_simple_lock_data(static,timer_call_lock)
47
1c79356b 48static struct {
1c79356b
A
49 int delayed_num,
50 delayed_hiwat;
55e303ae 51} timer_call_vars;
1c79356b
A
52
53static void
54timer_call_interrupt(
0b4e3aa0 55 uint64_t timestamp);
1c79356b
A
56
57#define qe(x) ((queue_entry_t)(x))
58#define TC(x) ((timer_call_t)(x))
59
60void
61timer_call_initialize(void)
62{
63 spl_t s;
1c79356b 64
91447636 65 simple_lock_init(&timer_call_lock, 0);
1c79356b
A
66
67 s = splclock();
68 simple_lock(&timer_call_lock);
69
1c79356b
A
70 clock_set_timer_func((clock_timer_func_t)timer_call_interrupt);
71
1c79356b
A
72 simple_unlock(&timer_call_lock);
73 splx(s);
74}
75
76void
77timer_call_setup(
78 timer_call_t call,
79 timer_call_func_t func,
80 timer_call_param_t param0)
81{
82 call_entry_setup(call, func, param0);
83}
84
85static __inline__
86void
87_delayed_call_enqueue(
88 queue_t queue,
89 timer_call_t call)
90{
91 timer_call_t current;
92
93 current = TC(queue_first(queue));
94
95 while (TRUE) {
0b4e3aa0
A
96 if ( queue_end(queue, qe(current)) ||
97 call->deadline < current->deadline ) {
1c79356b
A
98 current = TC(queue_prev(qe(current)));
99 break;
100 }
101
102 current = TC(queue_next(qe(current)));
103 }
104
105 insque(qe(call), qe(current));
55e303ae
A
106 if (++timer_call_vars.delayed_num > timer_call_vars.delayed_hiwat)
107 timer_call_vars.delayed_hiwat = timer_call_vars.delayed_num;
1c79356b
A
108
109 call->state = DELAYED;
110}
111
112static __inline__
113void
114_delayed_call_dequeue(
115 timer_call_t call)
116{
117 (void)remque(qe(call));
55e303ae 118 timer_call_vars.delayed_num--;
1c79356b
A
119
120 call->state = IDLE;
121}
122
1c79356b
A
123static __inline__
124void
125_set_delayed_call_timer(
126 timer_call_t call)
127{
8f6c56a5 128 clock_set_timer_deadline(call->deadline);
1c79356b
A
129}
130
131boolean_t
132timer_call_enter(
133 timer_call_t call,
0b4e3aa0 134 uint64_t deadline)
1c79356b
A
135{
136 boolean_t result = TRUE;
55e303ae 137 queue_t queue;
1c79356b
A
138 spl_t s;
139
140 s = splclock();
141 simple_lock(&timer_call_lock);
142
9bccf70c 143 if (call->state == DELAYED)
1c79356b 144 _delayed_call_dequeue(call);
9bccf70c 145 else
1c79356b
A
146 result = FALSE;
147
148 call->param1 = 0;
149 call->deadline = deadline;
150
91447636 151 queue = &PROCESSOR_DATA(current_processor(), timer_call_queue);
1c79356b 152
55e303ae 153 _delayed_call_enqueue(queue, call);
1c79356b 154
55e303ae 155 if (queue_first(queue) == qe(call))
1c79356b
A
156 _set_delayed_call_timer(call);
157
158 simple_unlock(&timer_call_lock);
159 splx(s);
160
161 return (result);
162}
163
164boolean_t
165timer_call_enter1(
166 timer_call_t call,
167 timer_call_param_t param1,
0b4e3aa0 168 uint64_t deadline)
1c79356b
A
169{
170 boolean_t result = TRUE;
55e303ae 171 queue_t queue;
1c79356b
A
172 spl_t s;
173
174 s = splclock();
175 simple_lock(&timer_call_lock);
176
9bccf70c 177 if (call->state == DELAYED)
1c79356b 178 _delayed_call_dequeue(call);
9bccf70c 179 else
1c79356b
A
180 result = FALSE;
181
182 call->param1 = param1;
183 call->deadline = deadline;
184
91447636 185 queue = &PROCESSOR_DATA(current_processor(), timer_call_queue);
1c79356b 186
55e303ae 187 _delayed_call_enqueue(queue, call);
1c79356b 188
55e303ae 189 if (queue_first(queue) == qe(call))
1c79356b
A
190 _set_delayed_call_timer(call);
191
192 simple_unlock(&timer_call_lock);
193 splx(s);
194
195 return (result);
196}
197
198boolean_t
199timer_call_cancel(
200 timer_call_t call)
201{
202 boolean_t result = TRUE;
203 spl_t s;
204
205 s = splclock();
206 simple_lock(&timer_call_lock);
207
9bccf70c 208 if (call->state == DELAYED)
1c79356b
A
209 _delayed_call_dequeue(call);
210 else
211 result = FALSE;
212
213 simple_unlock(&timer_call_lock);
214 splx(s);
215
216 return (result);
217}
218
219boolean_t
220timer_call_is_delayed(
221 timer_call_t call,
0b4e3aa0 222 uint64_t *deadline)
1c79356b
A
223{
224 boolean_t result = FALSE;
225 spl_t s;
226
227 s = splclock();
228 simple_lock(&timer_call_lock);
229
230 if (call->state == DELAYED) {
231 if (deadline != NULL)
232 *deadline = call->deadline;
233 result = TRUE;
234 }
235
236 simple_unlock(&timer_call_lock);
237 splx(s);
238
239 return (result);
240}
241
9bccf70c
A
242/*
243 * Called at splclock.
244 */
245
246void
247timer_call_shutdown(
248 processor_t processor)
249{
250 timer_call_t call;
55e303ae 251 queue_t queue, myqueue;
9bccf70c
A
252
253 assert(processor != current_processor());
254
91447636
A
255 queue = &PROCESSOR_DATA(processor, timer_call_queue);
256 myqueue = &PROCESSOR_DATA(current_processor(), timer_call_queue);
9bccf70c
A
257
258 simple_lock(&timer_call_lock);
259
55e303ae 260 call = TC(queue_first(queue));
9bccf70c 261
55e303ae 262 while (!queue_end(queue, qe(call))) {
9bccf70c
A
263 _delayed_call_dequeue(call);
264
55e303ae 265 _delayed_call_enqueue(myqueue, call);
9bccf70c 266
55e303ae 267 call = TC(queue_first(queue));
9bccf70c
A
268 }
269
55e303ae 270 call = TC(queue_first(myqueue));
9bccf70c 271
55e303ae 272 if (!queue_end(myqueue, qe(call)))
9bccf70c
A
273 _set_delayed_call_timer(call);
274
275 simple_unlock(&timer_call_lock);
276}
277
1c79356b
A
278static
279void
280timer_call_interrupt(
0b4e3aa0 281 uint64_t timestamp)
1c79356b
A
282{
283 timer_call_t call;
91447636 284 queue_t queue;
1c79356b
A
285
286 simple_lock(&timer_call_lock);
287
91447636
A
288 queue = &PROCESSOR_DATA(current_processor(), timer_call_queue);
289
55e303ae 290 call = TC(queue_first(queue));
1c79356b 291
55e303ae 292 while (!queue_end(queue, qe(call))) {
0b4e3aa0 293 if (call->deadline <= timestamp) {
1c79356b
A
294 timer_call_func_t func;
295 timer_call_param_t param0, param1;
296
297 _delayed_call_dequeue(call);
298
299 func = call->func;
300 param0 = call->param0;
301 param1 = call->param1;
302
303 simple_unlock(&timer_call_lock);
304
305 (*func)(param0, param1);
306
307 simple_lock(&timer_call_lock);
308 }
309 else
310 break;
311
55e303ae 312 call = TC(queue_first(queue));
1c79356b
A
313 }
314
55e303ae 315 if (!queue_end(queue, qe(call)))
1c79356b
A
316 _set_delayed_call_timer(call);
317
318 simple_unlock(&timer_call_lock);
319}