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
43struct thread_call;
44typedef struct thread_call *thread_call_t;
45
46typedef void *thread_call_param_t;
47typedef 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 */
68typedef 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
76enum {
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};
84typedef 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 */
99extern 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 */
111extern 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 */
127extern 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 */
141extern 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 */
202extern 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 */
222extern 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 */
240extern 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 */
252extern 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 */
266extern 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 */
282extern 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 */
300extern thread_call_t
301thread_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 */
313extern boolean_t
314thread_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 */
329extern 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 */
339boolean_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
347typedef 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
359struct 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
380typedef struct thread_call thread_call_data_t;
381
382extern void thread_call_initialize(void);
383
384extern void thread_call_setup(
385 thread_call_t call,
386 thread_call_func_t func,
387 thread_call_param_t param0);
388
389extern 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
403extern void thread_call_func_delayed(
404 thread_call_func_t func,
405 thread_call_param_t param,
406 uint64_t deadline);
407
408extern 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 */
421extern 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 */
429void adjust_cont_time_thread_calls(void);
430
431__END_DECLS
432
433#endif /* XNU_KERNEL_PRIVATE */
434
435#endif /* _KERN_THREAD_CALL_H_ */
436