Mach Kernel Abstractions and XNU Internals
Man is born free, and everywhere he is in chains. - Jean-Jacques Rousseau; The Social Contract
Search for the truth is the noblest occupation of man; its publication is a duty. - Anne Louise Germaine de Staël; De l'Allemagne
Preamble: XNU and the Mach Kernel
An operating system is a set of system software that acts as a bridge between the application software and the underlying hardware. Among the various software packaged with an operating system is the kernel — a program responsible for communicating with the hardware and managing the system in its entirety. The purpose of this post is to explore the XNU kernel source and understand the core abstractions of the Mach kernel that underpin the macOS kernel architecture. We'll walk through Mach's taxonomy — tasks, threads, IPC ports, processor sets — and examine the XNU-specific implementation details, including pointer authentication and key Mach routines like task_info and mach_task_self.
The Mach Kernel
Mach is a microkernel initially released in 1985. Since then, it has been incorporated on many Operating Systems such as GNU Hurd and Apple's XNU (see [XNU_GIT]). XNU is a kernel used by Darwin Operating System which is used in macOS and iOS operating systems. One of the major difference between the Mach kernel and Linux is the fact that various kernel subsystems can be modularized. Although the definition of a monolithic and a microkernel is mostly theoretical (see [MICRO_MONO_KERN]) while most production grade kernels have started to converge the properties of both monolithic and microkernel architecture into their implementation, there are still subtle differences between Mach and monolithic kernels such as Linux.
The aim of Mach kernel was to allow Operating Systems to be built on top of Mach. As with microkernel architecture, Mach only provides a smaller subset yet fundamental functionalities such as memory management, CPU scheduling, and inter-process communication. Do note that it is the BSD layer which is responsible for providing interfaces common in Operating Systems. Figure 1 shows the OSX architecture which is an excerpt from Wikipedia: Architecture of macOS.
Mach Kernel Abstractions in XNU
The section Mach Kernel Abstractions of [DEV_APPLE_MACH] briefly lays out the various abstractions offered by the Mach Kernel. In XNU, the structure of the said abstractions can be located. A quick browse of XNU source tree shows that there are various files and directories. Explaining all of the source is not the scope of this blog (see [MOSX_INTERNALS] and [OS_INTERNALS]), but we will try and locate the Mach-specific components of our interest. It should be known that [osfmk/] directory contains the componenets of the Mach kernel. Also, [bsd/] contains the BSD kernel components (see [BSD_ON_MACH]). Below gives the respective structure definitions of the various abstractions introduced by Mach:
-
Mach Tasks [osfmk/kern/task.h]. A container that contains various resources required for a "process". Essential resources include: virtual address space (
vm_map_t __ptrauth(...) map;) (see [XNU_PTRAUTH_SIGNED_PTR]), list of Mach threads (queue_head_t threads;), IPC space (struct ipc_port ...;), and also BSD info (struct proc_ro *bsd_info_ro;). Do note that the mentioned attributes alone does not constitute a Mach task and there exists much more attributes. -
Machine Independent Mach Threads [osfmk/kern/thread.h]. A kernel thread. It contains attributes such as Mach task (
struct task *t_task;), read-only thread zone (struct thread_ro *t_tro;), Asynchronous System Trap (AST) pending for the thread (ast_t volatile _Atomic ast;) (see [AST_ENUM_OPT_DECL]), current kernel stack (vm_offset_t kernel_stack;), machine-dependent thread state (struct machine_thread machine;), and other attributes.dangerOn Figure 7-10 of [MOSX_INTERNALS], the definition of
struct threadis shown. At the end, there is one field declared as:struct thread {
...
#ifdef MACH_BSD
void *uthread; // per-thread user structure
#endif
};However, the structure definition has changed since then. Until commit [
e6231be], theuthreadfield was present instruct thread. However, starting from commit [e777678], there no longer exists a distinctuthreadfield inside the structure.A Mach thread also has a 1:1 relation with the user thread (but there also could exist Mach threads with no associated user threads). This means that a user thread is associated with only one Mach thread. Upon looking at the
thread_create_internalfunction located in [osfmk/kern/thread.c], we see a line as:static kern_return_t
thread_create_internal (
task_t parent_task,
integer_t priority,
thread_continue_t continuation,
void *parameter,
thread_create_internal_options_t options,
thread_t *out_thread)
{
thread_t new_thread;
struct thread_ro tro_tpl = { };
...
/*
* Allocate a thread and initialize static fields
*/
new_thread = zalloc_flags(thread_zone, Z_WAITOK | Z_NOFAIL);
...
#ifdef MACH_BSD
uthread_init(parent_task, get_bsdthread_info(new_thread),
&tro_tpl, (options & (TH_OPTION_WORKQ | TH_OPTION_AIO_WORKQ)) != 0);
if (!task_is_a_corpse(parent_task)) {
/*
* uthread_init will set tro_cred (with a +1)
* and tro_proc for live tasks.
*/
assert(tro_tpl.tro_cred && tro_tpl.tro_proc);
}
#endif
...
}and (although not exactly required) the function
uthread_init(in [bsd/kern/kern_fork.c]) has the signature as:void uthread_init (task_t task, uthread_t uth, thread_ro_t tro_tpl, int workq_thread);Before I explain how the user thread structure is accessed from the Mach thread, let's see the type definition of
thread_tanduthread_t. On [osfmk/mach/mach_types.h], we see the two type definitions:...
#if KERNEL
/*
* If we are in the kernel, then pick up the kernel definitions for
* the basic mach types.
*/
...
typedef struct thread *thread_t, *thread_act_t, *thread_inspect_t, *thread_read_t;
...
#endif /* KERNEL */
...
/*
* If we are not in the kernel, then these will all be represented by
* ports at user-space.
*/
...
typedef mach_port_t thread_t;
...and since we're looking at the kernel implementation, it will indeed use the
struct threaddefinition forthread_t.For
uthread_t, it is type defined wherestruct uthreadis defined: [bsd/sys/user.h].typedef struct uthread * uthread_t;We'll explore the attributes of
struct uthreadlater. For now, let's inspect theget_bsdthread_infofunction which apparently takesthread_tas its argument and returns a pointer tostruct uthread. It is defined in [osfmk/kern/bsd_kern.c] as:struct uthread *
get_bsdthread_info(thread_t th)
{
return (struct uthread *)((uintptr_t)th + sizeof(struct thread));
}Notice that there is an offset of
sizeof(struct thread)applied to the pointer tostruct thread(which is essentially whatthis above). This would mean that a Mach thread structure is immediately followed by the corresponding user thread structure, in terms of addressing. Consequently, this function returns an address which lies just outside ofstruct threadand does an explicit cast tostruct uthread *.The reader should also be aware that previous commit of this file shows a different variation of
get_bsdthread_infofunction. Instead of doing pointer arithmetic to fetch the address to theuthreadstructure, it would simply return theuthreadfield that was present instruct threaditself. -
Machine Depenedent Mach Threads [osfmk/arm/thread.h] and [osfmk/i386/thread.h]. As seen in the comment in the source, this structure (for "historical reason") is also referred to as the Process Control Block (PCB) in the i386 structure definition. I'll discuss the ARM variant here. As seen in the machine independent structure above, it embeds the machine-dependent thread structure, containing attributes such as user context (
arm_context_t *contextData;) (see [MD_THREAD_CTX]), current per-CPU data (struct cpu_data *CpuDatap;), and plenty of reserved fields. -
BSD process [bsd/sys/proc_internal.h]. Earlier on Mach Tasks, we saw that a reference to BSD info is embedded within the structure (
bsd_info_ro). I should make the reader aware that it's the read-only data associated to a task and/or process, (see [bsd/sys/proc_ro.h]). The comment above the structure definition states that the lifetime of the read-only process structure is 1:1 with that of aproc_t(which is type definition of this structure) or atask_t(again, type definition of Mach task structure). Moreover, it also states that theproc_tandtask_tstructures point to the samestruct proc_rostructure, except for corpses. This structure contains attributes such as parent process ID (pid_t p_ppid;), process group ID (pid_t p_pgrpid;), various UNIX identifiers including user ID, group ID, real user ID, real group ID, session ID, list of processes in process group (LIST_ENTRY(proc) p_pglist;) (see [LIST_ENTRY]), open file structures (struct filedesc p_fd;), actions for signals (struct sigacts p_sigacts;) (see [PROC_SIGACTS]), and other attributes. -
User Threads [bsd/sys/user.h]. It is the BSD per-thread user structure. It contains various attributes, some being related to system calls (
uint64_t uu_args[8];andint uu_rval[2]), continuation attributes for some system calls, signals pending for the thread (sigset_t uu_siglist;), signal mask for the thread (sigset_t uu_sigmask;), list of user threads in [BSD] process (TAILQ_ENTRY(uthread) uu_list;) (see [TAILQ_ENTRY]), exit reason (struct os_reason *uu_exit_reason;), and other attributes. -
IPC Ports [osfmk/ipc/ipc_port.h].
-
Processor Set [osfmk/kern/processor.h]. Mach divides the available processors on a system into one or more processor sets. It is a logical grouping of processors.
cautionSection 7.2.2 of [MOSX_INTERNALS] describes the purpose of Processor Set as:
The original motivation behind processor sets was to group processors to allocate them to specific system activities--a coarse-grained allocation. Moreover, in early versions of Mac OS X, processor sets had associated scheduling policies and attributes, which provided a uniform control of the scheduling aspects of the threads in the set.
When the kernel starts up, a default processor set (
pset0on XNU) is initialized. Except for the default processor set, a processor set may contain zero processor. The default processor set must contain at least one processor. Furthermore, a processor must belong to atmost one processor set at a time.Under Processor Management of Chapter 9 (Volume 2) of [OS_INTERNALS], the following remark could be found regarding processor set:
Recall, that Mach allows for multiple processor sets (and processor nodes), which allows to quickly and easily scale up to Non-Uniform Memory Access (NUMA) and other distributed processing architectures. Apple, however, has neutered this in XNU, relying only on the single
pset0- returned by themach_hostsubsystem'sprocessor_set_default()Mach Interface Generator (MIG) routine. There are, at the time of writing, hints that this may finally change - at least in iOS, wherein the A-series processor's cores are asymmetric ("P"erformance cores and "E"fficiency cores), and could thus greatly benefit from a multi-set configuration.A more brief introduction on asymmetric as well as heterogeneous computing (which uses the notion of P and E cores described above; terminology commonly found in intel implementation) is given below (see [CORE]). Nevertheless, we notice that there is only one processor set object on the system;
pset0.Figure 7-2 of [MOSX_INTERNALS] has the following definition of structure
processor_set:// osfmk/kern/processor.h
struct processor_set {
queue_head_t idle_queue; // queue of idle processors
int idle_count; // how many idle processors?
queue_head_t active_queue; // queue of active processors
queue_head_t processors; // queue of all processors
...
};
extern struct processor_set default_set;On the current implementation, there does not exist explicit attribute on processor set object which references to the processor object.
-
Processor [osfmk/kern/processor.h]. A processor object is a logical representation of a physical processor. It may be a CPU, a core, or a hyperthread (see [SMT]).
Supplementary Notes
[MICRO_MONO_KERN] Despite their differences, many authors agree that the theoretical architectures often mislead the actual implementation. For example, although Linux is a monolithic kernel, subsystems like eBPF allow users to program the kernel at runtime, thereby exhibiting a property characteristic of microkernel architecture. For a deeper look at the classic BPF packet filter and its instruction set, see Berkeley Packet Filter (BPF): Packet Capture and Filtering in C. XNU--an open source kernel from Apple--can be considered as a monolithic kernel since the kernel task, a single task (with multiple threads), performs operation such as scheduling, thread reaping, callout management, paging, and UNIX exception handling. It can be considered as a monolithic kernel with different components such as Mach, BSD, and the I/O kit, all running as groups of threads in a single task in the same address space.
[BSD_ON_MACH] Although one might assume that the Mach kernel is a BSD-like kernel, this is not entirely correct. The BSD kernel found in OS X implementation is based upon FreeBSD. The Kernel Architecture Overview chapter illustrates the OS X architecture. We can observe that the BSD layer is built on top of the Mach kernel. In fact, a BSD process is one which has a corresponding Mach task assigned to it, but not all Mach task are required to have a BSD process.
[MD_THREAD_CTX] For ARM variant, the type arm_context_t is defined as typedef struct arm_context arm_context_t; and this structure inturn contains another structure member as struct arm_saved_state ss; along with another structure member for arm neon state (which we won't look into). struct arm_saved_state contains a union member as union { struct arm_saved_state32; struct arm_saved_state64; } uss;. When we look into any of the structure declared within the union, we observe that it contains information such as the array of general purpose registers, "special" registers such as the stack pointer, frame pointer, and such.
[PROC_SIGACTS] For details on the sigacts structure and how Mach exceptions are translated to UNIX signals via ux_exception.
[LIST_ENTRY] The macro used, LIST_ENTRY, is defined under [bsd/sys/queue.h] as:
#define LIST_ENTRY(type) \
__MISMATCH_TAGS_PUSH \
__NULLABILITY_COMPLETENESS_PUSH \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
} \
__NULLABILITY_COMPLETENESS_POP \
__MISMATCH_TAGS_POP
Although not needed, __MISMATCH_TAGS_PUSH and __MISMATCH_TAGS_POP expands to pragma operators for C++ (and when using clang(1) compiler), else to nothing. These macros too are defined in [bsd/sys/queue.h] with definition as:
#if defined(__clang__) && defined(__cplusplus)
#define __MISMATCH_TAGS_PUSH \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wmismatched-tags\"")
#define __MISMATCH_TAGS_POP \
_Pragma("clang diagnostic pop")
#else
#define __MISMATCH_TAGS_PUSH
#define __MISMATCH_TAGS_POP
#endif
Likewise, __NULLABILITY_COMPLETENESS_PUSH and __NULLABILITY_COMPLETENESS_POP only expand to pragma when compiling with clang. It is also defined in [bsd/sys/queue.h]. The definition is as follows:
#if defined(__clang__)
#define __NULLABILITY_COMPLETENESS_PUSH \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wnullability-completeness\"")
#define __NULLABILITY_COMPLETENESS_POP \
_Pragma("clang diagnostic pop")
#else
#define __NULLABILITY_COMPLETENESS_PUSH
#define __NULLABILITY_COMPLETENESS_POP
#endif
[TAILQ_ENTRY] The macro TAILQ_ENTRY is defined in [bsd/sys/queue.h] as:
#define TRACEBUF struct qm_trace trace;
#define TAILQ_ENTRY(type) \
__MISMATCH_TAGS_PUSH \
__NULLABILITY_COMPLETENESS_PUSH \
struct { \
struct type *tqe_next; /* next element */ \
struct type **tqe_prev; /* address of previous next element */ \
TRACEBUF \
} \
__NULLABILITY_COMPLETENESS_POP \
__MISMATCH_TAGS_POP
Except for the presence of another macro: TRACEBUF, it is similar to one described in [LIST_ENTRY].
XNU Implementation Details
The implementation patterns below make extensive use of C preprocessor techniques such as conditional compilation with __has_attribute and token pasting. For a focused walkthrough of how these techniques work in Apple's API_AVAILABLE macro, see How the API_AVAILABLE Macro Works on macOS.
This section documents some of the implementation found in the XNU source tree.
1. [XNU_PTRAUTH_SIGNED_PTR] In the source, we see the field declared as:
struct task {
...
vm_map_t XNU_PTRAUTH_SIGNED_PTR("task.map") map;
...
}
The arm64e specification introduced the notion of Pointer Authentication Code. Various articles are available on the web which explains this topic. If you want to explore it, Pointer Authentication documentation from clang explains this topic in an apparent manner. Getting back, XNU_PTRAUTH_SIGNED_PTR is a macro which is defined (in [libkern/os/base.h]) as:
#if KERNEL
#if __has_feature(ptrauth_calls)
#define XNU_PTRAUTH_SIGNED_FUNCTION_PTR(type) \
__ptrauth(ptrauth_key_function_pointer, 1, ptrauth_string_discriminator(type))
#else
#define XNU_PTRAUTH_SIGNED_FUNCTION_PTR(type)
#endif
#define XNU_PTRAUTH_SIGNED_PTR OS_PTRAUTH_SIGNED_PTR
#define XNU_PTRAUTH_SIGNED_PTR_AUTH_NULL OS_PTRAUTH_SIGNED_PTR_AUTH_NULL
#endif // KERNEL
The macro OS_PTRAUTH_SIGNED_PTR is also defined under the same file, [libkern/os/base.h], as:
#if KERNEL
#if __has_feature(ptrauth_calls)
#include <ptrauth.h>
#define OS_PTRAUTH_SIGNED_PTR(type) __ptrauth(ptrauth_key_process_independent_data, 1, ptrauth_string_discriminator(type))
#define OS_PTRAUTH_SIGNED_PTR_AUTH_NULL(type) __ptrauth(ptrauth_key_process_independent_data, 1, ptrauth_string_discriminator(type), "authenticates-null-values")
#define OS_PTRAUTH_DISCRIMINATOR(str) ptrauth_string_discriminator(str)
#define __ptrauth_only
#else // __has_feature(ptrauth_calls)
#define OS_PTRAUTH_SIGNED_PTR(type)
#define OS_PTRAUTH_SIGNED_PTR_AUTH_NULL(type)
#define OS_PTRAUTH_DISCRIMINATOR(str) 0
#define __ptrauth_only __unused
#endif // __has_feature(ptrauth_calls)
#endif // KERNEL
2. [AST_ENUM_OPT_DECL] In the source, we see the field declared as: os_atomic(ast_t) ast;. os_atomic is a parameterized macro that expands conditionally. In [libkern/os/atomic.h], there are two (conditional) macro definitions for os_atomic. From what I can tell, if C++ is used, it is defined as: #define os_atomic(type) std::atomic<type> volatile, and otherwise defined as: #define os_atomic(type) type volatile _Atomic.
Besides that, ast_t is an enumerable type, defined (in [osfmk/kern/ast.h]) as:
__options_decl(ast_t, uint32_t, {
AST_PREEMPT = 0x01,
AST_QUANTUM = 0x02,
AST_URGENT = 0x04,
AST_HANDOFF = 0x08,
AST_YIELD = 0x10,
AST_APC = 0x20, /* migration APC hook */
AST_LEDGER = 0x40,
AST_BSD = 0x80,
AST_KPERF = 0x100, /* kernel profiling */
AST_MACF = 0x200, /* MACF user ret pending */
AST_RESET_PCS = 0x400, /* restartable ranges */
AST_ARCADE = 0x800, /* arcade subsciption support */
AST_MACH_EXCEPTION = 0x1000,
AST_TELEMETRY_USER = 0x2000, /* telemetry sample requested on interrupt from userspace */
AST_TELEMETRY_KERNEL = 0x4000, /* telemetry sample requested on interrupt from kernel */
AST_TELEMETRY_PMI = 0x8000, /* telemetry sample requested on PMI */
AST_SFI = 0x10000, /* Evaluate if SFI wait is needed before return to userspace */
AST_DTRACE = 0x20000,
AST_TELEMETRY_IO = 0x40000, /* telemetry sample requested for I/O */
AST_KEVENT = 0x80000,
AST_REBALANCE = 0x100000, /* thread context switched due to rebalancing */
// was AST_UNQUIESCE 0x200000
AST_PROC_RESOURCE = 0x400000, /* port space and/or file descriptor table has reached its limits */
AST_DEBUG_ASSERT = 0x800000, /* check debug assertion */
AST_TELEMETRY_MACF = 0x1000000, /* telemetry sample requested by MAC framework */
AST_SYNTHESIZE_MACH = 0x2000000,
});
where __options_decl is a parameterized macro (defined in [bsd/sys/cdefs.h]) which expands as:
#if __has_attribute(enum_extensibility)
#define __enum_open __attribute__((__enum_extensibility__(open)))
#define __enum_closed __attribute__((__enum_extensibility__(closed)))
#else
#define __enum_open
#define __enum_closed
#endif // __has_attribute(enum_extensibility)
#if __has_attribute(flag_enum)
#define __enum_options __attribute__((__flag_enum__))
#else
#define __enum_options
#endif
#define __options_decl(_name, _type, ...) \
typedef enum : _type __VA_ARGS__ __enum_open __enum_options _name
The internal type used for an enumeration type is an integer. It is implementation defined whether the integer is signed or unsigned. Moreover, the width of the integer is usually that of int data type.
If we want to override the default implementation of the enumeration type (like shown above), the syntax would be:
enum : unsigned int {
FOO,
BAR,
BAZ
};
This is not defined in the C standard, but most compilers for the C language supports this extension for an enumeration type.
4. See TAILQ_ENTRY
Mach Kernel Routines
The description of most of these routines can be found in MIT: Mach IPC Interface
-
mach_task_self: Return a send right to the caller's task_self port.#include <mach/mach_traps.h>
/*
* param: none
*
* return: send right to the task's kernel port.
*/
mach_port_t
mach_task_self (void);cautionUnder
mach/mach_init.hfile, we see the declaration ofmach_task_selfas:extern mach_port_t mach_task_self_;
#define mach_task_self() mach_task_self_
#define current_task() mach_task_self() -
task_info: Return per-task information according to specified flavor.#include <mach/task.h>
/*
* params:
* task - The port of the task for which the information is to be returned.
* flavor - The type of information to be returned. See below.
* task_info - Information about the specified task.
* task_info_count - On input, the maximum size of the buffer; on output, the size returned (in natural-sized units).
*/
kern_return_t
task_info ( task_t task,
task_flavor_t flavor,
task_info_t task_info,
mach_msg_type_number_t task_info_count);The table below describes the various arguments to flavor, task_info, and task_info_count which is currently implemented in XNU (specifically [osfmk/kern/task.c]).
flavor task_info (address of) task_info_count Remark TASK_BASIC_INFO_32 struct task_basic_info_32 (task_basic_info_32_data_t) TASK_BASIC_INFO_32_COUNT Not preferred; use MACH_TASK_BASIC_INFO TASK_BASIC2_INFO_32 struct task_basic_info_32 (task_basic_info_32_data_t) TASK_BASIC_INFO_32_COUNT Not preferred; BASIC2 was used to get the maximum resident size instead of current resident size TASK_BASIC_INFO_64 struct task_basic_info_32 (task_basic_info_32_data_t) TASK_BASIC_INFO_32_COUNT Not preferred; only available on arm64 (non-arm64 described below) TASK_BASIC_INFO_64 struct task_basic_info_64 (task_basic_info_64_data_t) TASK_BASIC_INFO_64_COUNT Not preferred; used on non-arm64 variant TASK_BASIC_INFO_64_2 struct task_basic_info_64_2 (task_basic_info_64_2_data_t) TASK_BASIC_INFO_64_2_COUNT Not preferred; only available on arm64 MACH_TASK_BASIC_INFO struct mach_task_basic_info (mach_task_basic_info_data_t) MACH_TASK_BASIC_INFO_COUNT - TASK_THREAD_TIMES_INFO struct task_thread_times_info (task_thread_times_info_data_t) TASK_THREAD_TIMES_INFO_COUNT - TASK_ABSOLUTETIME_INFO struct task_absolutetime_info (task_absolutetime_info_data_t) TASK_ABSOLUTETIME_INFO_COUNT - TASK_DYLD_INFO struct task_dyld_info (task_dyld_info_data_t) TASK_DYLD_INFO_COUNT After the addition of all_image_info_formatfield,task_info_countcould be either TASK_DYLD_INFO_COUNT or the backward compatible TASK_LEGACY_DYLD_INFO_COUNTTASK_EXTMOD_INFO struct task_extmod_info (task_extmod_info_data_t) TASK_EXTMOD_INFO_COUNT - TASK_KERNELMEMORY_INFO struct task_kernelmemory_info (task_kernelmemory_info_data_t) TASK_KERNELMEMORY_INFO_COUNT - TASK_SCHED_FIFO_INFO struct policy_fifo_base (policy_fifo_base_data_t) POLICY_FIFO_BASE_COUNT Obsolete; see below TASK_SCHED_RR_INFO struct policy_rr_base (policy_rr_base_data_t) POLICY_RR_BASE_COUNT Obsolete; see below TASK_SCHED_TIMESHARE_INFO struct policy_timeshare_base (policy_timeshare_base_data_t) POLICY_TIMESHARE_BASE_COUNT Obsolete; see below TASK_SECURITY_TOKEN security_token_t (defined in mach/message.h)TASK_SECURITY_TOKEN_COUNT - TASK_AUDIT_TOKEN audit_token_t (defined in mach/message.h)TASK_AUDIT_TOKEN_COUNT - TASK_SCHED_INFO - - Obsolete TASK_EVENTS_INFO struct task_events_info (task_events_info_data_t) TASK_EVENTS_INFO_COUNT - TASK_AFFINITY_TAG_INFO struct task_affinity_tag_info (task_affinity_tag_info_data_t) TASK_AFFINITY_TAG_INFO_COUNT On task_info implementation of XNU, it appears to internally call task_affinity_infowhich is defined in [osfmk/kern/affinity.c]TASK_POWER_INFO struct task_power_info (task_power_info_data_t) TASK_POWER_INFO_COUNT On task_info implementation of XNU, it appears to internally call task_power_info_lockedwhich is defined in [osfmk/kern/task.c]TASK_POWER_INFO_V2 struct task_power_info_v2 (task_power_info_v2_data_t) TASK_POWER_INFO_V2_COUNT (or TASK_POWER_INFO_V2_COUNT_OLD) On task_info implementation of XNU, it only checks for TASK_POWER_INFO_V2_COUNT_OLD, and also calls task_power_info_lockedTASK_VM_INFO struct task_vm_info (task_vm_info_data_t) TASK_VM_INFO_COUNT The value of task_info_countcould also beTASK_VM_INFO_REV[0-7]_COUNT, whereTASK_INFO_REV7_COUNTis identical toTASK_VM_INFO_COUNT. The structure definition provides additional attributes for each new revision. Some additional checks is performed on arm64 architecture on Iphones (some apps passtask_info_countas count of bytes instead of count ofnatural_t) ...TASK_VM_INFO_PURGEABLE struct task_vm_info (task_vm_info_data_t) TASK_VM_INFO_COUNT ... and if the task is a kernel task, the internalfield oftask_vm_info_data_tis adjusted by considering the "memory held in VM compressor". Furthermore, whenTASK_VM_INFO_PURGEABLEis used,purgeable_volatile_[pmap|resident|virtual]attributes are appropriately returned. A series of checks for revision is performed and appropriate attributes are filledTASK_WAIT_STATE_INFO struct task_wait_state_info (task_wait_state_info_data_t) TASK_WAIT_STATE_INFO_COUNT Marked as deprecated with further note as, "Currently allowing some results until all users stop calling it. The results may not be accurate." TASK_VM_INFO_PURGEABLE_ACCOUNT struct pvm_account_info (pvm_account_info_data_t) PVM_ACCOUNT_INFO_COUNT Only visible in developement builds ( DEVELOPMENTorDEBUGsymbol must be present while compiling the kernel). ReturnsKERN_NOT_SUPPORTEDwhen used on production buildsTASK_FLAGS_INFO struct task_flags_info (task_flags_info_data_t) TASK_FLAGS_INFO_COUNT - TASK_DEBUG_INFO_INTERNAL struct task_debug_info_internal (task_debug_info_internal_data_t) TASK_DEBUG_INFO_INTERNAL_COUNT Only visible in developement builds ( DEVELOPMENTorDEBUGsymbol must be present while compiling the kernel). ReturnsKERN_NOT_SUPPORTEDwhen used on production buildsTASK_SUSPEND_STATS_INFO struct task_suspend_stats_s (task_suspend_stats_data_t) TASK_SUSPEND_STATS_INFO_COUNT Requires CONFIG_TASK_SUSPEND_STATSsymbol to be present along with either of debug symbol (DEVELOPMENTorDEBUG) when compiling the kernel to support this flavor. ReturnsKERN_NOT_SUPPORTEDwhen used on production buildsTASK_SUSPEND_SOURCES_INFO struct task_suspend_source_s (task_suspend_source_data_t) TASK_SUSPEND_SOURCES_INFO_COUNT Requires CONFIG_TASK_SUSPEND_STATSsymbol to be present along with either of debug symbol (DEVELOPMENTorDEBUG) when compiling the kernel to support this flavor. ReturnsKERN_NOT_SUPPORTEDwhen used on production buildsTASK_SECURITY_CONFIG_INFO struct task_security_config_info TASK_SECURITY_CONFIG_INFO_COUNT - TASK_IPC_SPACE_POLICY_INFO struct task_ipc_space_policy_info TASK_IPC_SPACE_POLICY_INFO_COUNT - dangerRegarding
TASK_SCHED_FIFO_INFO,TASK_SCHED_RR_INFO, andTASK_SCHED_TIMESHARE_INFO, until commit [c1dac77], XNU provided appropriatetask_infohandling capability. However, starting commit [8149afc], support forTASK_SCHED_FIFO_INFOwas removed. Although capability forTASK_SCHED_RR_INFOandTASK_SCHED_TIMESHARE_INFOstill exist, commit [14e3d83] marked them as obsolete.
References
[DEV_APPLE_MACH] https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/Mach/Mach.html
[APUE] Stevens, W.R., & Rago. S.A. (2013). Advanced Programming in Unix Environment.
[MOS] Tanenbaum, A.S., & Bos H. (2014). Modern Operating Systems.
[MOSX_INTERNALS] Singh, A (2007). Mac OS X Internals: A Systems Approach.
[OS_INTERNALS] Levin, J (2016, 2017, 2019) MacOS and iOS Internals Trilogy. https://www.newosxbook.com/index.php
[INTEL_HVHCE] https://www.intel.com/content/www/us/en/docs/sycl/introduction/latest/01-homogeneous-vs-heterogeneous.html
[XNU_GIT] https://github.com/apple-oss-distributions/xnu
[Draves 91] http://staff.ustc.edu.cn/~bjhua/courses/ats/2014/ref/draves91continuations.pdf
[COMMIT] f6217f891ac0bb64f3d375211650a4c1ff8ca1ea
