2 * Copyright (c) 1993-1995, 1999-2008 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * @header thread_call.h
31 * @discussion Facilities for executing work asynchronously.
34 #ifndef _KERN_THREAD_CALL_H_
35 #define _KERN_THREAD_CALL_H_
37 #include <mach/mach_types.h>
39 #include <kern/clock.h>
41 #include <sys/cdefs.h>
44 typedef struct thread_call
*thread_call_t
;
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
);
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
61 * @constant THREAD_CALL_PRIORITY_KERNEL Importance similar to that of normal kernel
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
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
;
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 */
84 typedef uint32_t thread_call_options_t
;
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.
99 extern boolean_t
thread_call_enter(
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.
111 extern boolean_t
thread_call_enter1(
113 thread_call_param_t param1
);
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.
127 extern boolean_t
thread_call_enter_delayed(
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.
141 extern boolean_t
thread_call_enter1_delayed(
143 thread_call_param_t param1
,
145 #ifdef XNU_KERNEL_PRIVATE
148 * Flags to alter the default timer/timeout coalescing behavior
149 * on a per-thread_call basis.
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).
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.
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
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
169 #define THREAD_CALL_DELAY_URGENCY_MASK TIMEOUT_URGENCY_MASK
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.
177 #define THREAD_CALL_DELAY_LEEWAY TIMEOUT_URGENCY_LEEWAY
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.
184 #define THREAD_CALL_CONTINUOUS 0x100
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.
202 extern boolean_t
thread_call_enter_delayed_with_leeway(
204 thread_call_param_t param1
,
209 #endif /* XNU_KERNEL_PRIVATE */
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.
222 extern boolean_t
thread_call_cancel(
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.
240 extern boolean_t
thread_call_cancel_wait(
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.
252 extern thread_call_t
thread_call_allocate(
253 thread_call_func_t func
,
254 thread_call_param_t param0
);
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.
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
);
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.
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
);
288 #ifdef KERNEL_PRIVATE
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.
301 thread_call_allocate_with_qos(thread_call_func_t func
,
302 thread_call_param_t param0
,
304 thread_call_options_t options
);
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
314 thread_call_wait_once(thread_call_t call
);
315 #endif /* KERNEL_PRIVATE */
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.
329 extern boolean_t
thread_call_free(
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.
339 boolean_t
thread_call_isactive(
343 #ifdef MACH_KERNEL_PRIVATE
345 #include <kern/queue.h>
346 #include <kern/priority_queue.h>
348 __enum_closed_decl(thread_call_index_t
, uint16_t, {
349 THREAD_CALL_INDEX_HIGH
= 0,
350 THREAD_CALL_INDEX_KERNEL
= 1,
351 THREAD_CALL_INDEX_USER
= 2,
352 THREAD_CALL_INDEX_LOW
= 3,
353 THREAD_CALL_INDEX_KERNEL_HIGH
= 4,
354 THREAD_CALL_INDEX_QOS_UI
= 5,
355 THREAD_CALL_INDEX_QOS_IN
= 6,
356 THREAD_CALL_INDEX_QOS_UT
= 7,
357 THREAD_CALL_INDEX_MAX
= 8, /* count of thread call indexes */
360 __options_closed_decl(thread_call_flags_t
, uint16_t, {
361 THREAD_CALL_ALLOC
= 0x0001, /* memory owned by thread_call.c */
362 THREAD_CALL_WAIT
= 0x0002, /* thread waiting for call to finish running */
363 THREAD_CALL_DELAYED
= 0x0004, /* deadline based */
364 THREAD_CALL_RUNNING
= 0x0008, /* currently executing on a thread */
365 THREAD_CALL_SIGNAL
= 0x0010, /* call from timer interrupt instead of thread */
366 THREAD_CALL_ONCE
= 0x0020, /* pend the enqueue if re-armed while running */
367 THREAD_CALL_RESCHEDULE
= 0x0040, /* enqueue is pending due to re-arm while running */
368 THREAD_CALL_RATELIMITED
= 0x0080, /* timer doesn't fire until slop+deadline */
369 THREAD_CALL_FLAG_CONTINUOUS
= 0x0100, /* deadline is in continuous time */
373 /* Originally requested deadline */
374 uint64_t tc_soft_deadline
;
375 /* Deadline presented to hardware (post-leeway) stored in tc_pqlink.deadline */
376 struct priority_queue_entry_deadline tc_pqlink
;
377 /* Which queue head is this call enqueued on */
378 queue_head_t
*tc_queue
;
379 queue_chain_t tc_qlink
;
380 thread_call_index_t tc_index
;
381 thread_call_flags_t tc_flags
;
383 /* Time to deadline at creation */
385 /* Timestamp of enqueue on pending queue */
386 uint64_t tc_pending_timestamp
;
387 thread_call_func_t tc_func
;
388 thread_call_param_t tc_param0
;
389 thread_call_param_t tc_param1
;
390 uint64_t tc_submit_count
;
391 uint64_t tc_finish_count
;
394 typedef struct thread_call thread_call_data_t
;
396 extern void thread_call_initialize(void);
398 extern void thread_call_setup(
400 thread_call_func_t func
,
401 thread_call_param_t param0
);
403 extern void thread_call_setup_with_options(
405 thread_call_func_t func
,
406 thread_call_param_t param0
,
407 thread_call_priority_t pri
,
408 thread_call_options_t options
);
410 extern void thread_call_delayed_timer_rescan_all(void);
411 extern uint64_t thread_call_get_armed_deadline(thread_call_t call
);
413 struct thread_call_thread_state
;
415 #endif /* MACH_KERNEL_PRIVATE */
417 #ifdef XNU_KERNEL_PRIVATE
422 * These routines are equivalent to their thread_call_enter_XXX
423 * variants, only the thread_call_t is allocated out of a
424 * fixed preallocated pool of memory, and will panic if the pool
428 extern void thread_call_func_delayed(
429 thread_call_func_t func
,
430 thread_call_param_t param
,
433 extern void thread_call_func_delayed_with_leeway(
434 thread_call_func_t func
,
435 thread_call_param_t param
,
441 * This iterates all of the pending or delayed thread calls in the group,
442 * which is really inefficient.
444 * This is deprecated, switch to an allocated thread call instead.
446 extern boolean_t
thread_call_func_cancel(
447 thread_call_func_t func
,
448 thread_call_param_t param
,
449 boolean_t cancel_all
);
452 * Called on the wake path to adjust the thread callouts running in mach_continuous_time
454 extern void adjust_cont_time_thread_calls(void);
456 /* called by IOTimerEventSource to track when the workloop lock has been taken */
457 extern void thread_call_start_iotes_invocation(thread_call_t call
);
461 #endif /* XNU_KERNEL_PRIVATE */
463 #endif /* _KERN_THREAD_CALL_H_ */