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