]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/timer_call.c
xnu-792.13.8.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
5d5c5d0d
A
48#include <sys/kdebug.h>
49
1c79356b
A
50decl_simple_lock_data(static,timer_call_lock)
51
1c79356b 52static struct {
1c79356b
A
53 int delayed_num,
54 delayed_hiwat;
55e303ae 55} timer_call_vars;
1c79356b
A
56
57static void
58timer_call_interrupt(
0b4e3aa0 59 uint64_t timestamp);
1c79356b
A
60
61#define qe(x) ((queue_entry_t)(x))
62#define TC(x) ((timer_call_t)(x))
63
64void
65timer_call_initialize(void)
66{
67 spl_t s;
1c79356b 68
91447636 69 simple_lock_init(&timer_call_lock, 0);
1c79356b
A
70
71 s = splclock();
72 simple_lock(&timer_call_lock);
73
1c79356b
A
74 clock_set_timer_func((clock_timer_func_t)timer_call_interrupt);
75
1c79356b
A
76 simple_unlock(&timer_call_lock);
77 splx(s);
78}
79
80void
81timer_call_setup(
82 timer_call_t call,
83 timer_call_func_t func,
84 timer_call_param_t param0)
85{
86 call_entry_setup(call, func, param0);
87}
88
89static __inline__
90void
91_delayed_call_enqueue(
92 queue_t queue,
93 timer_call_t call)
94{
95 timer_call_t current;
96
97 current = TC(queue_first(queue));
98
99 while (TRUE) {
0b4e3aa0
A
100 if ( queue_end(queue, qe(current)) ||
101 call->deadline < current->deadline ) {
1c79356b
A
102 current = TC(queue_prev(qe(current)));
103 break;
104 }
105
106 current = TC(queue_next(qe(current)));
107 }
108
109 insque(qe(call), qe(current));
55e303ae
A
110 if (++timer_call_vars.delayed_num > timer_call_vars.delayed_hiwat)
111 timer_call_vars.delayed_hiwat = timer_call_vars.delayed_num;
1c79356b
A
112
113 call->state = DELAYED;
114}
115
116static __inline__
117void
118_delayed_call_dequeue(
119 timer_call_t call)
120{
121 (void)remque(qe(call));
55e303ae 122 timer_call_vars.delayed_num--;
1c79356b
A
123
124 call->state = IDLE;
125}
126
1c79356b
A
127static __inline__
128void
129_set_delayed_call_timer(
130 timer_call_t call)
131{
5d5c5d0d 132 etimer_set_deadline(call->deadline);
1c79356b
A
133}
134
135boolean_t
136timer_call_enter(
137 timer_call_t call,
0b4e3aa0 138 uint64_t deadline)
1c79356b
A
139{
140 boolean_t result = TRUE;
55e303ae 141 queue_t queue;
1c79356b
A
142 spl_t s;
143
144 s = splclock();
145 simple_lock(&timer_call_lock);
146
9bccf70c 147 if (call->state == DELAYED)
1c79356b 148 _delayed_call_dequeue(call);
9bccf70c 149 else
1c79356b
A
150 result = FALSE;
151
152 call->param1 = 0;
153 call->deadline = deadline;
154
91447636 155 queue = &PROCESSOR_DATA(current_processor(), timer_call_queue);
1c79356b 156
55e303ae 157 _delayed_call_enqueue(queue, call);
1c79356b 158
55e303ae 159 if (queue_first(queue) == qe(call))
1c79356b
A
160 _set_delayed_call_timer(call);
161
162 simple_unlock(&timer_call_lock);
163 splx(s);
164
165 return (result);
166}
167
168boolean_t
169timer_call_enter1(
170 timer_call_t call,
171 timer_call_param_t param1,
0b4e3aa0 172 uint64_t deadline)
1c79356b
A
173{
174 boolean_t result = TRUE;
55e303ae 175 queue_t queue;
1c79356b
A
176 spl_t s;
177
178 s = splclock();
179 simple_lock(&timer_call_lock);
180
9bccf70c 181 if (call->state == DELAYED)
1c79356b 182 _delayed_call_dequeue(call);
9bccf70c 183 else
1c79356b
A
184 result = FALSE;
185
186 call->param1 = param1;
187 call->deadline = deadline;
188
91447636 189 queue = &PROCESSOR_DATA(current_processor(), timer_call_queue);
1c79356b 190
55e303ae 191 _delayed_call_enqueue(queue, call);
1c79356b 192
55e303ae 193 if (queue_first(queue) == qe(call))
1c79356b
A
194 _set_delayed_call_timer(call);
195
196 simple_unlock(&timer_call_lock);
197 splx(s);
198
199 return (result);
200}
201
202boolean_t
203timer_call_cancel(
204 timer_call_t call)
205{
206 boolean_t result = TRUE;
207 spl_t s;
208
209 s = splclock();
210 simple_lock(&timer_call_lock);
211
9bccf70c 212 if (call->state == DELAYED)
1c79356b
A
213 _delayed_call_dequeue(call);
214 else
215 result = FALSE;
216
217 simple_unlock(&timer_call_lock);
218 splx(s);
219
220 return (result);
221}
222
223boolean_t
224timer_call_is_delayed(
225 timer_call_t call,
0b4e3aa0 226 uint64_t *deadline)
1c79356b
A
227{
228 boolean_t result = FALSE;
229 spl_t s;
230
231 s = splclock();
232 simple_lock(&timer_call_lock);
233
234 if (call->state == DELAYED) {
235 if (deadline != NULL)
236 *deadline = call->deadline;
237 result = TRUE;
238 }
239
240 simple_unlock(&timer_call_lock);
241 splx(s);
242
243 return (result);
244}
245
9bccf70c
A
246/*
247 * Called at splclock.
248 */
249
250void
251timer_call_shutdown(
252 processor_t processor)
253{
254 timer_call_t call;
55e303ae 255 queue_t queue, myqueue;
9bccf70c
A
256
257 assert(processor != current_processor());
258
91447636
A
259 queue = &PROCESSOR_DATA(processor, timer_call_queue);
260 myqueue = &PROCESSOR_DATA(current_processor(), timer_call_queue);
9bccf70c
A
261
262 simple_lock(&timer_call_lock);
263
55e303ae 264 call = TC(queue_first(queue));
9bccf70c 265
55e303ae 266 while (!queue_end(queue, qe(call))) {
9bccf70c
A
267 _delayed_call_dequeue(call);
268
55e303ae 269 _delayed_call_enqueue(myqueue, call);
9bccf70c 270
55e303ae 271 call = TC(queue_first(queue));
9bccf70c
A
272 }
273
55e303ae 274 call = TC(queue_first(myqueue));
9bccf70c 275
55e303ae 276 if (!queue_end(myqueue, qe(call)))
9bccf70c
A
277 _set_delayed_call_timer(call);
278
279 simple_unlock(&timer_call_lock);
280}
281
1c79356b
A
282static
283void
284timer_call_interrupt(
0b4e3aa0 285 uint64_t timestamp)
1c79356b
A
286{
287 timer_call_t call;
91447636 288 queue_t queue;
1c79356b
A
289
290 simple_lock(&timer_call_lock);
291
91447636
A
292 queue = &PROCESSOR_DATA(current_processor(), timer_call_queue);
293
55e303ae 294 call = TC(queue_first(queue));
1c79356b 295
55e303ae 296 while (!queue_end(queue, qe(call))) {
5d5c5d0d 297
0b4e3aa0 298 if (call->deadline <= timestamp) {
1c79356b
A
299 timer_call_func_t func;
300 timer_call_param_t param0, param1;
301
302 _delayed_call_dequeue(call);
303
304 func = call->func;
305 param0 = call->param0;
306 param1 = call->param1;
307
308 simple_unlock(&timer_call_lock);
309
5d5c5d0d
A
310 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 2) | DBG_FUNC_START, (int)func, param0, param1, 0, 0);
311
1c79356b
A
312 (*func)(param0, param1);
313
5d5c5d0d
A
314 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_DECI, 2) | DBG_FUNC_END, (int)func, param0, param1, 0, 0);
315
1c79356b
A
316 simple_lock(&timer_call_lock);
317 }
318 else
319 break;
320
55e303ae 321 call = TC(queue_first(queue));
1c79356b
A
322 }
323
55e303ae 324 if (!queue_end(queue, qe(call)))
1c79356b
A
325 _set_delayed_call_timer(call);
326
327 simple_unlock(&timer_call_lock);
5d5c5d0d 328
1c79356b 329}