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