| 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/queue.h> |
| 346 | #include <kern/priority_queue.h> |
| 347 | |
| 348 | __enum_closed_decl(thread_call_index_t, uint16_t, { |
| 349 | THREAD_CALL_INDEX_INVALID = 0, /* make sure zero tc_index is detected as invalid */ |
| 350 | THREAD_CALL_INDEX_HIGH = 1, |
| 351 | THREAD_CALL_INDEX_KERNEL = 2, |
| 352 | THREAD_CALL_INDEX_USER = 3, |
| 353 | THREAD_CALL_INDEX_LOW = 4, |
| 354 | THREAD_CALL_INDEX_KERNEL_HIGH = 5, |
| 355 | THREAD_CALL_INDEX_QOS_UI = 6, |
| 356 | THREAD_CALL_INDEX_QOS_IN = 7, |
| 357 | THREAD_CALL_INDEX_QOS_UT = 8, |
| 358 | THREAD_CALL_INDEX_MAX = 9, /* count of thread call indexes */ |
| 359 | }); |
| 360 | |
| 361 | __options_closed_decl(thread_call_flags_t, uint16_t, { |
| 362 | THREAD_CALL_ALLOC = 0x0001, /* memory owned by thread_call.c */ |
| 363 | THREAD_CALL_WAIT = 0x0002, /* thread waiting for call to finish running */ |
| 364 | THREAD_CALL_DELAYED = 0x0004, /* deadline based */ |
| 365 | THREAD_CALL_RUNNING = 0x0008, /* currently executing on a thread */ |
| 366 | THREAD_CALL_SIGNAL = 0x0010, /* call from timer interrupt instead of thread */ |
| 367 | THREAD_CALL_ONCE = 0x0020, /* pend the enqueue if re-armed while running */ |
| 368 | THREAD_CALL_RESCHEDULE = 0x0040, /* enqueue is pending due to re-arm while running */ |
| 369 | THREAD_CALL_RATELIMITED = 0x0080, /* timer doesn't fire until slop+deadline */ |
| 370 | THREAD_CALL_FLAG_CONTINUOUS = 0x0100, /* deadline is in continuous time */ |
| 371 | THREAD_CALL_INITIALIZED = 0x0200, /* thread call is initialized */ |
| 372 | }); |
| 373 | |
| 374 | struct thread_call { |
| 375 | /* Originally requested deadline */ |
| 376 | uint64_t tc_soft_deadline; |
| 377 | /* Deadline presented to hardware (post-leeway) stored in tc_pqlink.deadline */ |
| 378 | struct priority_queue_entry_deadline tc_pqlink; |
| 379 | /* Which queue head is this call enqueued on */ |
| 380 | queue_head_t *tc_queue; |
| 381 | queue_chain_t tc_qlink; |
| 382 | thread_call_index_t tc_index; |
| 383 | thread_call_flags_t tc_flags; |
| 384 | int32_t tc_refs; |
| 385 | /* Time to deadline at creation */ |
| 386 | uint64_t tc_ttd; |
| 387 | /* Timestamp of enqueue on pending queue */ |
| 388 | uint64_t tc_pending_timestamp; |
| 389 | thread_call_func_t tc_func; |
| 390 | thread_call_param_t tc_param0; |
| 391 | thread_call_param_t tc_param1; |
| 392 | uint64_t tc_submit_count; |
| 393 | uint64_t tc_finish_count; |
| 394 | }; |
| 395 | |
| 396 | typedef struct thread_call thread_call_data_t; |
| 397 | |
| 398 | extern void thread_call_setup( |
| 399 | thread_call_t call, |
| 400 | thread_call_func_t func, |
| 401 | thread_call_param_t param0); |
| 402 | |
| 403 | extern void thread_call_setup_with_options( |
| 404 | thread_call_t call, |
| 405 | thread_call_func_t func, |
| 406 | thread_call_param_t param0, |
| 407 | thread_call_priority_t pri, |
| 408 | thread_call_options_t options); |
| 409 | |
| 410 | extern void thread_call_delayed_timer_rescan_all(void); |
| 411 | extern uint64_t thread_call_get_armed_deadline(thread_call_t call); |
| 412 | |
| 413 | struct thread_call_thread_state; |
| 414 | |
| 415 | #endif /* MACH_KERNEL_PRIVATE */ |
| 416 | |
| 417 | #ifdef XNU_KERNEL_PRIVATE |
| 418 | |
| 419 | __BEGIN_DECLS |
| 420 | |
| 421 | /* |
| 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 |
| 425 | * is exhausted. |
| 426 | */ |
| 427 | |
| 428 | extern void thread_call_func_delayed( |
| 429 | thread_call_func_t func, |
| 430 | thread_call_param_t param, |
| 431 | uint64_t deadline); |
| 432 | |
| 433 | extern void thread_call_func_delayed_with_leeway( |
| 434 | thread_call_func_t func, |
| 435 | thread_call_param_t param, |
| 436 | uint64_t deadline, |
| 437 | uint64_t leeway, |
| 438 | uint32_t flags); |
| 439 | |
| 440 | /* |
| 441 | * This iterates all of the pending or delayed thread calls in the group, |
| 442 | * which is really inefficient. |
| 443 | * |
| 444 | * This is deprecated, switch to an allocated thread call instead. |
| 445 | */ |
| 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); |
| 450 | |
| 451 | /* |
| 452 | * Called on the wake path to adjust the thread callouts running in mach_continuous_time |
| 453 | */ |
| 454 | extern void adjust_cont_time_thread_calls(void); |
| 455 | |
| 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); |
| 458 | |
| 459 | __END_DECLS |
| 460 | |
| 461 | #endif /* XNU_KERNEL_PRIVATE */ |
| 462 | |
| 463 | #endif /* _KERN_THREAD_CALL_H_ */ |
| 464 | |