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