1 | /* |
2 | * Copyright (c) 1993-1995, 1999-2008 Apple Inc. All rights reserved. |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | * |
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. |
14 | * |
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 |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
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. |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ |
28 | |
29 | /*! |
30 | @header thread_call.h |
31 | @discussion Facilities for executing work asynchronously. |
32 | */ |
33 | |
34 | #ifndef _KERN_THREAD_CALL_H_ |
35 | #define _KERN_THREAD_CALL_H_ |
36 | |
37 | #include <mach/mach_types.h> |
38 | |
39 | #include <kern/clock.h> |
40 | |
41 | #include <sys/cdefs.h> |
42 | |
43 | struct thread_call; |
44 | typedef struct thread_call *thread_call_t; |
45 | |
46 | typedef void *thread_call_param_t; |
47 | typedef void (*thread_call_func_t)( |
48 | thread_call_param_t param0, |
49 | thread_call_param_t param1); |
50 | /*! |
51 | @enum thread_call_priority_t |
52 | @discussion Thread call priorities should not be assumed to have any specific |
53 | numerical value; they should be interpreted as importances or roles for work |
54 | items, priorities for which will be reasonably managed by the subsystem. |
55 | @constant THREAD_CALL_PRIORITY_HIGH Importance above everything but realtime. |
56 | Thread calls allocated with this priority execute at extremely high priority, |
57 | above everything but realtime threads. They are generally executed in serial. |
58 | Though they may execute concurrently under some circumstances, no fan-out is implied. |
59 | These work items should do very small amounts of work or risk disrupting system |
60 | responsiveness. |
61 | @constant THREAD_CALL_PRIORITY_KERNEL Importance similar to that of normal kernel |
62 | threads. |
63 | @constant THREAD_CALL_PRIORITY_USER Importance similar to that of normal user threads. |
64 | @constant THREAD_CALL_PRIORITY_LOW Very low importance. |
65 | @constant THREAD_CALL_PRIORITY_KERNEL_HIGH Importance higher than most kernel |
66 | threads. |
67 | */ |
68 | typedef enum { |
69 | THREAD_CALL_PRIORITY_HIGH = 0, |
70 | THREAD_CALL_PRIORITY_KERNEL = 1, |
71 | THREAD_CALL_PRIORITY_USER = 2, |
72 | THREAD_CALL_PRIORITY_LOW = 3, |
73 | THREAD_CALL_PRIORITY_KERNEL_HIGH = 4 |
74 | } thread_call_priority_t; |
75 | |
76 | enum { |
77 | /* if call is re-submitted while the call is executing on a call thread, then delay the re-enqueue until it returns */ |
78 | THREAD_CALL_OPTIONS_ONCE = 0x00000001, |
79 | #ifdef XNU_KERNEL_PRIVATE |
80 | /* execute call from the timer interrupt instead of from the thread call thread, private interface for IOTES workloop signaling */ |
81 | THREAD_CALL_OPTIONS_SIGNAL = 0x00000002, |
82 | #endif /* XNU_KERNEL_PRIVATE */ |
83 | }; |
84 | typedef uint32_t thread_call_options_t; |
85 | |
86 | __BEGIN_DECLS |
87 | |
88 | /*! |
89 | @function thread_call_enter |
90 | @abstract Submit a thread call work item for immediate execution. |
91 | @discussion If the work item is already scheduled for delayed execution, and it has |
92 | not yet begun to run, that delayed invocation will be cancelled. Note that if a |
93 | thread call is rescheduled from its own callback, then multiple invocations of the |
94 | callback may be in flight at the same time. |
95 | @result TRUE if the call was already pending for either delayed or immediate |
96 | execution, FALSE otherwise. |
97 | @param call The thread call to execute. |
98 | */ |
99 | extern boolean_t thread_call_enter( |
100 | thread_call_t call); |
101 | /*! |
102 | @function thread_call_enter1 |
103 | @abstract Submit a thread call work item for immediate execution, with an extra parameter. |
104 | @discussion This routine is identical to thread_call_enter(), except that |
105 | the second parameter to the callback is specified. |
106 | @result TRUE if the call was already pending for either delayed or immediate |
107 | execution, FALSE otherwise. |
108 | @param call The thread call to execute. |
109 | @param param1 Parameter to pass callback. |
110 | */ |
111 | extern boolean_t thread_call_enter1( |
112 | thread_call_t call, |
113 | thread_call_param_t param1); |
114 | |
115 | /*! |
116 | @function thread_call_enter_delayed |
117 | @abstract Submit a thread call to be executed at some point in the future. |
118 | @discussion If the work item is already scheduled for delayed or immediate execution, |
119 | and it has not yet begun to run, that invocation will be cancelled in favor of execution |
120 | at the newly specified time. Note that if a thread call is rescheduled from its own callback, |
121 | then multiple invocations of the callback may be in flight at the same time. |
122 | @result TRUE if the call was already pending for either delayed or immediate |
123 | execution, FALSE otherwise. |
124 | @param call The thread call to execute. |
125 | @param deadline Time, in absolute time units, at which to execute callback. |
126 | */ |
127 | extern boolean_t thread_call_enter_delayed( |
128 | thread_call_t call, |
129 | uint64_t deadline); |
130 | /*! |
131 | @function thread_call_enter1_delayed |
132 | @abstract Submit a thread call to be executed at some point in the future, with an extra parameter. |
133 | @discussion This routine is identical to thread_call_enter_delayed(), |
134 | except that a second parameter to the callback is specified. |
135 | @result TRUE if the call was already pending for either delayed or immediate |
136 | execution, FALSE otherwise. |
137 | @param call The thread call to execute. |
138 | @param param1 Second parameter to callback. |
139 | @param deadline Time, in absolute time units, at which to execute callback. |
140 | */ |
141 | extern boolean_t thread_call_enter1_delayed( |
142 | thread_call_t call, |
143 | thread_call_param_t param1, |
144 | uint64_t deadline); |
145 | #ifdef XNU_KERNEL_PRIVATE |
146 | |
147 | /* |
148 | * Flags to alter the default timer/timeout coalescing behavior |
149 | * on a per-thread_call basis. |
150 | * |
151 | * The SYS urgency classes indicate that the thread_call is not |
152 | * directly related to the current thread at the time the thread_call |
153 | * is entered, so it is ignored in the calculation entirely (only |
154 | * the subclass specified is used). |
155 | * |
156 | * The USER flags indicate that both the current thread scheduling and QoS |
157 | * attributes, in addition to the per-thread_call urgency specification, |
158 | * are used to establish coalescing behavior. |
159 | */ |
160 | #define THREAD_CALL_DELAY_SYS_NORMAL TIMEOUT_URGENCY_SYS_NORMAL |
161 | #define THREAD_CALL_DELAY_SYS_CRITICAL TIMEOUT_URGENCY_SYS_CRITICAL |
162 | #define THREAD_CALL_DELAY_SYS_BACKGROUND TIMEOUT_URGENCY_SYS_BACKGROUND |
163 | |
164 | #define THREAD_CALL_DELAY_USER_MASK TIMEOUT_URGENCY_USER_MASK |
165 | #define THREAD_CALL_DELAY_USER_NORMAL TIMEOUT_URGENCY_USER_NORMAL |
166 | #define THREAD_CALL_DELAY_USER_CRITICAL TIMEOUT_URGENCY_USER_CRITICAL |
167 | #define THREAD_CALL_DELAY_USER_BACKGROUND TIMEOUT_URGENCY_USER_BACKGROUND |
168 | |
169 | #define THREAD_CALL_DELAY_URGENCY_MASK TIMEOUT_URGENCY_MASK |
170 | |
171 | /* |
172 | * Indicate that a specific leeway value is being provided (otherwise |
173 | * the leeway parameter is ignored). The supplied value can currently |
174 | * only be used to extend the leeway calculated internally from the |
175 | * urgency class provided. |
176 | */ |
177 | #define THREAD_CALL_DELAY_LEEWAY TIMEOUT_URGENCY_LEEWAY |
178 | |
179 | /* |
180 | * Indicates that the time parameters should be interpreted as |
181 | * mach_continuous_time values, rather than mach_absolute_time and the timer |
182 | * be programmed to fire based on continuous time. |
183 | */ |
184 | #define THREAD_CALL_CONTINUOUS 0x100 |
185 | |
186 | /*! |
187 | @function thread_call_enter_delayed_with_leeway |
188 | @abstract Submit a thread call to be executed at some point in the future. |
189 | @discussion If the work item is already scheduled for delayed or immediate execution, |
190 | and it has not yet begun to run, that invocation will be cancelled in favor of execution |
191 | at the newly specified time. Note that if a thread call is rescheduled from its own callback, |
192 | then multiple invocations of the callback may be in flight at the same time. |
193 | @result TRUE if the call was already pending for either delayed or immediate |
194 | execution, FALSE otherwise. |
195 | @param call The thread call to execute. |
196 | @param param1 Second parameter to callback. |
197 | @param deadline Time, in absolute time units, at which to execute callback. |
198 | @param leeway Time delta, in absolute time units, which sets range of time allowing kernel |
199 | to decide appropriate time to run. |
200 | @param flags configuration for timers in kernel. |
201 | */ |
202 | extern boolean_t thread_call_enter_delayed_with_leeway( |
203 | thread_call_t call, |
204 | thread_call_param_t param1, |
205 | uint64_t deadline, |
206 | uint64_t leeway, |
207 | uint32_t flags); |
208 | |
209 | #endif /* XNU_KERNEL_PRIVATE */ |
210 | |
211 | /*! |
212 | @function thread_call_cancel |
213 | @abstract Attempt to cancel a pending invocation of a thread call. |
214 | @discussion Attempt to cancel a thread call which has been scheduled |
215 | for execution with a thread_call_enter* variant. If the call has not |
216 | yet begun executing, the pending invocation will be cancelled and TRUE |
217 | will be returned. If the work item has already begun executing, |
218 | thread_call_cancel will return FALSE immediately; the callback may be |
219 | about to run, currently running, or already done executing. |
220 | @result TRUE if the call was successfully cancelled, FALSE otherwise. |
221 | */ |
222 | extern boolean_t thread_call_cancel( |
223 | thread_call_t call); |
224 | /*! |
225 | @function thread_call_cancel_wait |
226 | @abstract Attempt to cancel a pending invocation of a thread call. |
227 | If unable to cancel, wait for current invocation to finish. |
228 | @discussion Attempt to cancel a thread call which has been scheduled |
229 | for execution with a thread_call_enter* variant. If the call has not |
230 | yet begun executing, the pending invocation will be cancelled and TRUE |
231 | will be returned. If the work item has already begun executing, |
232 | thread_call_cancel_wait waits for the most recent invocation to finish. When |
233 | called on a work item which has already finished, it will return FALSE immediately. |
234 | Note that this routine can only be used on thread calls set up with either |
235 | thread_call_allocate or thread_call_allocate_with_priority, and that invocations |
236 | of the thread call <i>after</i> the current invocation may be in flight when |
237 | thread_call_cancel_wait returns. |
238 | @result TRUE if the call was successfully cancelled, FALSE otherwise. |
239 | */ |
240 | extern boolean_t thread_call_cancel_wait( |
241 | thread_call_t call); |
242 | |
243 | /*! |
244 | @function thread_call_allocate |
245 | @abstract Allocate a thread call to execute with default (high) priority. |
246 | @discussion Allocates a thread call that will run with properties of |
247 | THREAD_CALL_PRIORITY_HIGH, binding the first parameter to the callback. |
248 | @param func Callback to invoke when thread call is scheduled. |
249 | @param param0 First argument ot pass to callback. |
250 | @result Thread call which can be passed to thread_call_enter variants. |
251 | */ |
252 | extern thread_call_t thread_call_allocate( |
253 | thread_call_func_t func, |
254 | thread_call_param_t param0); |
255 | |
256 | /*! |
257 | @function thread_call_allocate_with_priority |
258 | @abstract Allocate a thread call to execute with a specified priority. |
259 | @discussion Identical to thread_call_allocate, except that priority |
260 | is specified by caller. |
261 | @param func Callback to invoke when thread call is scheduled. |
262 | @param param0 First argument to pass to callback. |
263 | @param pri Priority of item. |
264 | @result Thread call which can be passed to thread_call_enter variants. |
265 | */ |
266 | extern thread_call_t thread_call_allocate_with_priority( |
267 | thread_call_func_t func, |
268 | thread_call_param_t param0, |
269 | thread_call_priority_t pri); |
270 | |
271 | /*! |
272 | @function thread_call_allocate_with_options |
273 | @abstract Allocate a thread call to execute with a specified priority. |
274 | @discussion Identical to thread_call_allocate, except that priority |
275 | and options are specified by caller. |
276 | @param func Callback to invoke when thread call is scheduled. |
277 | @param param0 First argument to pass to callback. |
278 | @param pri Priority of item. |
279 | @param options Options for item. |
280 | @result Thread call which can be passed to thread_call_enter variants. |
281 | */ |
282 | extern thread_call_t thread_call_allocate_with_options( |
283 | thread_call_func_t func, |
284 | thread_call_param_t param0, |
285 | thread_call_priority_t pri, |
286 | thread_call_options_t options); |
287 | |
288 | #ifdef KERNEL_PRIVATE |
289 | /*! |
290 | @function thread_call_allocate_with_qos |
291 | @abstract Allocate a thread call to execute with a specified QoS. |
292 | @discussion Identical to thread_call_allocate_with_options, except it uses the QoS namespace. |
293 | Private interface for pthread kext. |
294 | @param func Callback to invoke when thread call is scheduled. |
295 | @param param0 First argument to pass to callback. |
296 | @param qos_tier QoS tier to execute callback at (as in THREAD_QOS_POLICY) |
297 | @param options flags from thread_call_options_t to influence the thread call behavior |
298 | @result Thread call which can be passed to thread_call_enter variants. |
299 | */ |
300 | extern thread_call_t |
301 | thread_call_allocate_with_qos(thread_call_func_t func, |
302 | thread_call_param_t param0, |
303 | int qos_tier, |
304 | thread_call_options_t options); |
305 | |
306 | /*! |
307 | @function thread_call_wait_once |
308 | @abstract Wait for a THREAD_CALL_OPTIONS_ONCE call to finish executing if it is executing |
309 | @discussion Only works on THREAD_CALL_OPTIONS_ONCE calls |
310 | @param call The thread call to wait for |
311 | @result True if it waited, false if it did not wait |
312 | */ |
313 | extern boolean_t |
314 | thread_call_wait_once(thread_call_t call); |
315 | #endif /* KERNEL_PRIVATE */ |
316 | |
317 | /*! |
318 | @function thread_call_free |
319 | @abstract Release a thread call. |
320 | @discussion Should only be used on thread calls allocated with thread_call_allocate |
321 | or thread_call_allocate_with_priority. Once thread_call_free has been called, |
322 | no other operations may be performed on a thread call. If the thread call is |
323 | currently pending, thread_call_free will return FALSE and will have no effect. |
324 | Calling thread_call_free from a thread call's own callback is safe; the work |
325 | item is not considering "pending" at that point. |
326 | @result TRUE if the thread call has been successfully released, else FALSE. |
327 | @param call The thread call to release. |
328 | */ |
329 | extern boolean_t thread_call_free( |
330 | thread_call_t call); |
331 | |
332 | /*! |
333 | @function thread_call_isactive |
334 | @abstract Determine whether a thread call is pending or currently executing. |
335 | @param call Thread call to examine. |
336 | @result TRUE if the thread call is either scheduled for execution (immediately |
337 | or at some point in the future) or is currently executing. |
338 | */ |
339 | boolean_t thread_call_isactive( |
340 | thread_call_t call); |
341 | __END_DECLS |
342 | |
343 | #ifdef MACH_KERNEL_PRIVATE |
344 | |
345 | #include <kern/call_entry.h> |
346 | |
347 | typedef enum { |
348 | THREAD_CALL_INDEX_HIGH = 0, |
349 | THREAD_CALL_INDEX_KERNEL = 1, |
350 | THREAD_CALL_INDEX_USER = 2, |
351 | THREAD_CALL_INDEX_LOW = 3, |
352 | THREAD_CALL_INDEX_KERNEL_HIGH = 4, |
353 | THREAD_CALL_INDEX_QOS_UI = 5, |
354 | THREAD_CALL_INDEX_QOS_IN = 6, |
355 | THREAD_CALL_INDEX_QOS_UT = 7, |
356 | THREAD_CALL_INDEX_MAX = 8, /* count of thread call indexes */ |
357 | } thread_call_index_t; |
358 | |
359 | struct thread_call { |
360 | struct call_entry tc_call; /* Must be first for queue macros */ |
361 | uint64_t tc_submit_count; |
362 | uint64_t tc_finish_count; |
363 | uint64_t tc_ttd; /* Time to deadline at creation */ |
364 | uint64_t tc_soft_deadline; |
365 | thread_call_index_t tc_index; |
366 | uint32_t tc_flags; |
367 | int32_t tc_refs; |
368 | }; |
369 | |
370 | #define THREAD_CALL_ALLOC 0x01 /* memory owned by thread_call.c */ |
371 | #define THREAD_CALL_WAIT 0x02 /* thread waiting for call to finish running */ |
372 | #define THREAD_CALL_DELAYED 0x04 /* deadline based */ |
373 | #define THREAD_CALL_RUNNING 0x08 /* currently executing on a thread */ |
374 | #define THREAD_CALL_SIGNAL 0x10 /* call from timer interrupt instead of thread */ |
375 | #define THREAD_CALL_ONCE 0x20 /* pend the enqueue if re-armed while running */ |
376 | #define THREAD_CALL_RESCHEDULE 0x40 /* enqueue is pending due to re-arm while running */ |
377 | #define THREAD_CALL_RATELIMITED TIMEOUT_URGENCY_RATELIMITED /* 0x80 */ |
378 | /* THREAD_CALL_CONTINUOUS 0x100 */ |
379 | |
380 | typedef struct thread_call thread_call_data_t; |
381 | |
382 | extern void thread_call_initialize(void); |
383 | |
384 | extern void thread_call_setup( |
385 | thread_call_t call, |
386 | thread_call_func_t func, |
387 | thread_call_param_t param0); |
388 | |
389 | extern void thread_call_delayed_timer_rescan_all(void); |
390 | #endif /* MACH_KERNEL_PRIVATE */ |
391 | |
392 | #ifdef XNU_KERNEL_PRIVATE |
393 | |
394 | __BEGIN_DECLS |
395 | |
396 | /* |
397 | * These routines are equivalent to their thread_call_enter_XXX |
398 | * variants, only the thread_call_t is allocated out of a |
399 | * fixed preallocated pool of memory, and will panic if the pool |
400 | * is exhausted. |
401 | */ |
402 | |
403 | extern void thread_call_func_delayed( |
404 | thread_call_func_t func, |
405 | thread_call_param_t param, |
406 | uint64_t deadline); |
407 | |
408 | extern void thread_call_func_delayed_with_leeway( |
409 | thread_call_func_t func, |
410 | thread_call_param_t param, |
411 | uint64_t deadline, |
412 | uint64_t leeway, |
413 | uint32_t flags); |
414 | |
415 | /* |
416 | * This iterates all of the pending or delayed thread calls in the group, |
417 | * which is really inefficient. |
418 | * |
419 | * This is deprecated, switch to an allocated thread call instead. |
420 | */ |
421 | extern boolean_t thread_call_func_cancel( |
422 | thread_call_func_t func, |
423 | thread_call_param_t param, |
424 | boolean_t cancel_all); |
425 | |
426 | /* |
427 | * Called on the wake path to adjust the thread callouts running in mach_continuous_time |
428 | */ |
429 | void adjust_cont_time_thread_calls(void); |
430 | |
431 | __END_DECLS |
432 | |
433 | #endif /* XNU_KERNEL_PRIVATE */ |
434 | |
435 | #endif /* _KERN_THREAD_CALL_H_ */ |
436 | |