XXNU Source Handbook Offline reading instructions
Part 05 · Chapter 05.01

BSD processes and the POSIX interface

Guide index · Architecture

This part of XNU turns Mach tasks and threads into processes with PIDs, parent/child relationships, credentials, file descriptors, signals, and system calls. It also provides event delivery and the kernel side of pthread workqueues. BSD runs in the kernel address space and calls Mach directly; it is not a separate user process serving POSIX requests.

These pages describe the supplied xnu-12377.121.6 source snapshot. Configuration guards matter: a declaration in syscalls.master does not establish that a feature is enabled in a particular shipped kernel. No running-kernel experiments or kernel build were performed for this chapter.

For descriptor storage, read filedesc tables and slot publication and fileproc/fileglob allocation and lifetime beside descriptor operations. The companions separate movable arrays, per-descriptor I/O holds, shared offsets/references, guarded variants and final endpoint close.

Read in this order

For the structures behind these operations, use the process and its protected data and the task and its shared RO data. They follow zone allocation, validated access, field updates and the two sides of final reclamation; the RO update walkthrough carries those writes into the selected pmap backend.

Thread and uthread storage follows BSD initialization, credential caches, process associations and their cleanup. Credential storage and replacement supplies the allocation, uniquing and ownership model behind UID/GID changes and exec identity publication.

  1. Process objects and lifetime: the initial map of proc, task, thread, and uthread; continue with Fork, spawn, exec, exit, and wait for publication gates, failure paths, reference drains, and reaping.
  2. System calls, signals, and exceptions: syscall entry and the exception bridge; continue with Signal posting, handler entry, and sigreturn for target selection, AST processing, ARM64 frames, and validation.
  3. File descriptors: allocation, replacement and close: reserved slots, table growth, fileproc/fileglob ownership, constructor publication, dup2 replacement, I/O drains, guarded operations and fileport transfer.
  4. Events, pthreads, and workqueues: the initial event/thread map; continue with Kqueue, knote, and workloop lifetimes for registration, posting, delivery, drop, owner, and servicer protocols.
  5. Pthread boundaries, workqueue service, and cancellation: request admission, creator selection, binding, worker reuse/parking, cancellation, join wake, and teardown.
  6. Asynchronous file I/O: request ownership, both worker paths, cancellation races, result consumption, and close/exec/exit drains.
  7. Complete BSD syscall catalog: dispatch/argument/result state, every master-table slot and conditional alternative, and each active call's purpose and local mechanism. Compare the separate Mach namespaces and AST flavor catalog.

For exec's identity changes, read Exec identity and inherited state: set-ID predicates, group membership, MAC transitions, Mach inheritance resets, descriptor repair, credential publication and task tokens follow separate decisions. Continue with Exec arguments and the initial user stack for argument extraction, interpreter rewriting, byte budgets, Apple entries and a worked ARM64 startup layout. ARM64 thread-state conversion continues the signal-return route through pointer conversion and saved-state installation.

Process inspection and snapshots follows proc_info from selectors and process identity checks into descriptor lists and typed descriptor details. Its concurrent example distinguishes a retained object during one query from identity across separate queries.

For local communication and terminals, continue with:

Chapter Mechanism
Pipes and UNIX socket rights Buffer ownership, atomic writes, peer closure, descriptor transfer and collection of unreachable rights cycles
User-address wait and wake Private/shared keys, protected comparison, unfair-lock inheritance, wake selection and final-waiter cleanup
POSIX named IPC Named semaphore creation/wait/unlink and shared-memory name, descriptor, memory-entry and mapping lifetime
System V IPC Message storage and copy failure, semaphore vectors and undo, segment IDs, attachments and removal
TTY and PTY lifecycle Terminal input/output queues, canonical/raw completion, PTY dispatch, job control and hangup/reclamation

The objects that connect the layers

BSD processes and the POSIX interface diagram
BSD processes and the POSIX interface diagram · Open SVG
Mermaid source
flowchart TB
    U[Userspace: POSIX and pthread calls] --> S[BSD syscall dispatch]
    S --> P[proc: PID, family, files, signal actions]
    S --> UT[uthread: syscall state and pending signals]
    P --- RO[proc_ro: identity and credential association]
    RO --- T[Mach task: VM map and IPC space]
    UT --- TH[Mach thread: scheduling and machine state]
    TH --> T
    P --> FD[filedesc → fileproc → fileglob]
    FD --> V[Vnodes / sockets / pipes / kqueues]
    V --> K[Knotes and event delivery]
    K --> W[Workqueue thread requests]
    W --> TH

The stable distinction is process policy versus execution mechanism. proc stores the Unix process model; task owns the Mach execution environment; thread is scheduled; uthread supplies BSD state for that thread. The implementation deliberately ties their lifetimes together without making their roles interchangeable. Current credential pointers are in thread_ro, so older descriptions placing a uu_ucred field in uthread do not match this snapshot.

Boundary Concrete connection Continue reading
Mach execution fork_create_child() calls task_create_internal() and creates the main thread; final Mach thread termination calls proc_exit() Runtime
Virtual memory Fork requests memory inheritance; exec loads a new Mach-O map VM
Mach IPC Task/thread ports become accessible after initialization; exception messages become signals; workloops receive Mach-port events IPC
Filesystems Exec resolves a vnode; descriptors dispatch through fileops; filedesc holds current/root directories VFS
Networking Socket descriptors share the descriptor machinery; local sockets transport descriptor references Networking
Security Credentials, MAC checks, executable policy, and audit hooks appear throughout process transitions Security
Architecture Trap entry and signal frames use saved machine state Platform

Sources inspected and limits

“Deep” below means structures and selected complete control/lifetime paths were read. It does not mean every line of these large files was audited.

Source area Inspection Remaining limits
proc_internal.h, proc_ro.h, user.h, kern_proc.c Deep: fields, references, PID lookup, exec drains, proc/task relationship Process groups, personas, accounting, and all reference-debug cases were not exhaustively traced
kern_fork.c, kern_exec.c, kern_exit.c Deep: creation/rollback, spawn action and credential ordering, shadow-proc exec publication/gates/failure, exit ownership, ordered teardown, wait/reap Mach-O parser and every spawn attribute/failure branch are outside this chapter
systemcalls.c, syscalls.master, kern_sig.c, ux_exception.c Deep: ARM dispatcher, restart/error return, posting/AST handling, ARM64 frame construction and sigreturn validation, exception translation x86/ARM32 signal frames and libsyscall generation were surveyed; full ptrace/job-control behavior remains broader
kern_descrip.c, sys_generic.c, descriptor headers Deep: reservation/table-growth retry, construction/publication/rollback, lookup/drop, fork copying, dup2 replacement, I/O drain and final close, selected guard predicates and fileport lifetime Every fcntl command, guard-change combination and endpoint-specific drain remains broader; AIO and local IPC have separate focused guides
kern_aio.c Deep selected paths: request/ref ownership, validation/enqueue, both workers, completion/consumption, cancellation queue-removal race, close/exec/exit/pool drains Every batch, fsync dependency, AIO filter, and worker-admission transition is not audited
kern_event.c, event headers, pthread_workqueue.c, pthread_shims.c Deep selected paths: knote register/post/process/drop, fd close, dynamic workloop owner/servicer/retain/turnstile, requests/admission, worker creation/park/exit, pthread boundary Every filter, work-interval/cooperative scheduling policy, and priority/parking race remains broader; external pthread implementation is absent
sys_pipe.c, uipc_usrreq.c, sys_ulock.c Pipe buffering/wait/close, UNIX rights conversion and cycle collection, ulock key/compare/inheritance/wake/cleanup Selected implementation paths, not a formal concurrency proof; userspace lock algorithms remain external
POSIX/SysV IPC files, tty.c, tty_dev.c, tty_ptmx.c Named IPC namespace and backing lifetime, SysV queues/vectors/undo/attachments, TTY queues/job control and PTY teardown Configuration-dependent IPC families; physical terminal drivers and userspace terminal emulation remain external

The principal code-reading trap is treating historical comments as the current object layout. Confirm descriptions against declarations and executable branches: exec now replaces a proc/task pair, filedesc is embedded in proc, and some pthread operations cross a function-table boundary into separately supplied code.

Search the handbook

Search every chapter, interface and code excerpt.

    Diagram

    Source preview

    Open full file