#include <kern/kern_types.h>
kern/kern_types.h
typedefevent64_t
Events are used to selectively wake up threads waiting
on a specified wait queue.
The NO_EVENT64 value is a special event that is used
on wait queues that can be members of wait queue sets
for waits/wakeups that need to prepost to the set.
This event must be "unique" and it is customary to use
a pointer to memory related to the event.
typedef uint64_t event64_t
64 bit wait event
macroNO_EVENT64
#define NO_EVENT64 ((event64_t) 0)
macroCAST_EVENT64_T
#define CAST_EVENT64_T(a_ptr) ((event64_t)((uintptr_t)(a_ptr)))
typedefthread_continue_t
typedef void (*thread_continue_t)(void *, wait_result_t)
macroTHREAD_CONTINUE_NULL
#define THREAD_CONTINUE_NULL ((thread_continue_t) NULL)
typedefwait_interrupt_t
Interruptible flag for waits.
THREAD_UNINT: Uninterruptible wait
Wait will only end when someone explicitly wakes up the thread, or if the
wait timeout expires.
Use this state if the system as a whole cannot recover from a thread being
interrupted out of the wait.
THREAD_INTERRUPTIBLE:
Wait will end if someone explicitly wakes up the thread, the wait timeout
expires, or the current thread is being terminated.
This value can be used when your operation may not be cleanly restartable
for the current process or thread (i.e. the loss of state would be only visible
to the current client). Since the thread is exiting anyways, you're willing
to cut the operation short. The system as a whole must be able to cleanly
deal with the interruption (i.e. remain in a consistent and recoverable state).
THREAD_ABORTSAFE:
Wait will end if someone explicitly wakes up the thread, the wait timeout
expires, the current thread is being terminated, if any signal arrives for
the task, or thread_abort_safely() is called on the thread.
Using this value means that you are willing to be interrupted in the face
of any user signal, and safely rewind the thread back to the user/kernel
boundary. Many syscalls will try to restart the operation they were performing
after the signal has been handled.
You must provide this value for any unbounded wait - otherwise you will
pend user signals forever.
THREAD_WAIT_NOREPORT:
The scheduler has a callback (sched_call) that some subsystems use to
decide whether more threads should be thrown at a given problem by trying
to maintain a good level of concurrency.
When the wait will not be helped by adding more threads (e.g. lock
contention), using this flag as an argument to assert_wait* (or any of its
wrappers) will prevent the next wait/block to cause thread creation.
This comes in two flavors: THREAD_WAIT_NOREPORT_KERNEL, and
THREAD_WAIT_NOREPORT_USER to prevent reporting about the wait for kernel
and user threads respectively.
Thread interrupt mask:
The current maximum interruptible state for the thread, as set by
thread_interrupt_level(), will limit the conditions that will cause a wake.
This is useful for code that can't be interrupted to set before calling code
that doesn't know that.
Thread termination vs safe abort:
Termination abort: thread_abort(), thread_terminate()
A termination abort is sticky. Once a thread is marked for termination, every
THREAD_INTERRUPTIBLE wait will return immediately with THREAD_INTERRUPTED
until the thread successfully exits.
Safe abort: thread_abort_safely()
A safe abort is not sticky. The current wait, (or the next wait if the thread
is not currently waiting) will be interrupted, but then the abort condition is cleared.
The next wait will sleep as normal. Safe aborts only have a single effect.
The path back to the user/kernel boundary must not make any further unbounded
wait calls. The waiter should detect the THREAD_INTERRUPTED return code
from an ABORTSAFE wait and return an error code that causes its caller
to understand that the current operation has been interrupted, and its
caller should return a similar error code, and so on until the
user/kernel boundary is reached. For Mach, the error code is usually KERN_ABORTED,
for BSD it is EINTR.
Debuggers rely on the safe abort mechanism - a signaled thread must return to
the AST at the user/kernel boundary for the debugger to finish attaching.
No wait/block will ever disappear a thread out from under the waiter. The block
call will always either return or call the passed in continuation.
typedef int wait_interrupt_t
macroTHREAD_WAIT_NOREPORT_KERNEL
#define THREAD_WAIT_NOREPORT_KERNEL 0x80000000
macroTHREAD_WAIT_NOREPORT_USER
#define THREAD_WAIT_NOREPORT_USER 0x40000000
macroTHREAD_WAIT_NOREPORT
#define THREAD_WAIT_NOREPORT (THREAD_WAIT_NOREPORT_KERNEL | THREAD_WAIT_NOREPORT_USER)
typedefwait_timeout_urgency_t
typedef int wait_timeout_urgency_t
macroTIMEOUT_URGENCY_SYS_NORMAL
#define TIMEOUT_URGENCY_SYS_NORMAL 0x00
use default leeway thresholds for system
macroTIMEOUT_URGENCY_SYS_CRITICAL
#define TIMEOUT_URGENCY_SYS_CRITICAL 0x01
use critical leeway thresholds for system
macroTIMEOUT_URGENCY_SYS_BACKGROUND
#define TIMEOUT_URGENCY_SYS_BACKGROUND 0x02
use background leeway thresholds for system
macroTIMEOUT_URGENCY_USER_MASK
#define TIMEOUT_URGENCY_USER_MASK 0x10
mask to identify user timeout urgency classes
macroTIMEOUT_URGENCY_USER_NORMAL
#define TIMEOUT_URGENCY_USER_NORMAL 0x10
use default leeway thresholds for user
macroTIMEOUT_URGENCY_USER_CRITICAL
#define TIMEOUT_URGENCY_USER_CRITICAL 0x11
use critical leeway thresholds for user
macroTIMEOUT_URGENCY_USER_BACKGROUND
#define TIMEOUT_URGENCY_USER_BACKGROUND 0x12
use background leeway thresholds for user
macroTIMEOUT_URGENCY_FIRST_AVAIL
#define TIMEOUT_URGENCY_FIRST_AVAIL 0x40
first available bit outside of urgency mask/leeway
macroTIMEOUT_URGENCY_RATELIMITED
#define TIMEOUT_URGENCY_RATELIMITED 0x80
macroTIMEOUT_NO_LEEWAY
Timeout and deadline tokens for waits.
The following tokens define common values for leeway and deadline parameters.
#define TIMEOUT_NO_LEEWAY (0ULL)
macroTIMEOUT_WAIT_FOREVER
#define TIMEOUT_WAIT_FOREVER (0ULL)