Skip to content

Kernel Data Structures

kazah-png edited this page Aug 16, 2026 · 5 revisions

Kernel data structures

Field-by-field reference for the core kernel structures. Definitions live in kernel/core/kernel.h unless stated otherwise; this page documents what each field means and which code owns it.

See also: Process-Management, Filesystem, GUI-Subsystem, SMP, Syscalls

process_t

The process table entry. One per task — kernel thread, user process, or CLONE_VM thread. Table size is MAX_PROCESSES (512).

Identity

Field Type Meaning
pid uint32_t Process id
ppid uint32_t Parent's pid
uid / euid uint32_t Real / effective user id (tracked, not enforced — see Security)
gid / egid uint32_t Real / effective group id
comm[32] char Short name, set by proc_set_comm(); surfaces in ps and /proc/<pid>/status
cmdline[256] char Full command line; surfaces in /proc/<pid>/cmdline

Address space and stacks

Field Type Meaning
page_directory void* This task's PML4. NULL for a kernel thread
stack void* Saved kernel-stack pointer where this task's registers were last pushed — the incoming RSP a context switch restores (see Process-Management#Context switching). A middle pointer, not the allocation base
kernel_stack void* Per-process syscall stack, stored as the higher-half alias; loaded into TSS.RSP0 and kernel_rsp when this task is scheduled
program_break uint64_t Top of the heap, moved by SYS_SBRK
heap_start uint64_t Initial break. [heap_start, program_break) is the lazy-sbrk fault-in window

Warning

stack points into the middle of its allocation; the kmalloc base is kernel_stack - 4096. Calling kfree(proc->stack) corrupts the heap. This was a real bug — see the v5.6.0 entry in Version-History.

Important

kernel_stack must hold the higher-half alias, not the low kmalloc address. Once the scheduler switches to the user CR3 the low address is unmapped, and the next entry faults into a triple fault.

Scheduling

Field Type Meaning
state uint32_t PROC_* — see the state table below
priority uint32_t Legacy; the scheduler uses sched_weight
cpu_time uint32_t Accumulated ticks; the TIME column in ps
start_time uint32_t tick_count at creation
sched_managed uint32_t 1 = round-robined by the preemptive scheduler
sched_weight uint32_t Ticks per turn (0 ⇒ 1). The compositor uses SCHED_WEIGHT_GUI = 4
sched_quantum uint32_t Ticks left in the current turn (scheduler-internal)
sched_cpu int32_t 0 = BSP, N > 0 = that AP exclusively. Pinning is the mutual-exclusion argument for SMP
exit_code int Status passed to SYS_EXIT, collected by waitpid

Blocking

Field Type Meaning
waiting_for uint32_t pid this task is blocked in kwait() on. 0 = wait-any, or not waiting
wake_tick uint32_t tick_count at which a sleep()-blocked task wakes. 0 = not sleeping
futex_key uint64_t Physical address this task is FUTEX_WAIT-blocked on. 0 = not
blocked_in_kernel uint32_t 1 = parked mid-syscall in ring 0

Note

blocked_in_kernel tells the scheduler to resume the task on the kernel CR3. Kernel code built -mcmodel=large runs at low link addresses that are only mapped there.

Process states

Constant Value Meaning
PROC_PARKED 0 Not runnable — a retired kernel thread; the scheduler skips it
PROC_RUN 1 Runnable or running
PROC_ZOMBIE 2 Exited, awaiting reap_zombies()
PROC_BLOCKED 3 Blocked in kwait(), sleep(), read(), futex_wait()
PROC_STOPPED 4 Job-control stopped by SIGTSTP/SIGSTOP, parked until SIGCONT

Thread group

Field Type Meaning
tgid uint32_t pid of the group leader. 0 or == pid means this task is the leader

CLONE_VM threads defer to the leader through tg_leader(), so sbrk and mmap performed by any thread are seen by all of them. The fd table is shared per group too.

File descriptors

Field Type Meaning
files[MAX_FILES] void* Legacy kernel handle array
ufd_handle[PROC_MAX_FDS] int Internal VFS handle, or a pipe/socket id with a flag bit
ufd_offset[PROC_MAX_FDS] uint32_t Per-fd byte offset, advanced by read/write
ufd_inuse[PROC_MAX_FDS] uint8_t Slot occupancy

PROC_MAX_FDS is 32. Userspace sees UFD_BASE + slot, never the internal handle.

Flag Meaning
UFD_PIPE_FLAG The handle is a pipe end
UFD_SOCK_FLAG The handle is a network socket

close_proc_fds() runs at reap, so a crashed process cannot leak VFS handles.

Signals

Field Type Meaning
sig_pending uint32_t Bit i set = signal i is pending
sig_mask uint32_t Bit i set = signal i is blocked
sig_active uint32_t Bit i set = handler for i is currently on the user stack
sig_handlers[NSIG] uint64_t 0 = SIG_DFL, 1 = SIG_IGN, else a ring-3 handler address
sig_trampoline uint64_t Ring-3 __sigreturn address, from libc
sig_saved[18] uint64_t Saved context: [0..14] GPRs r15…rax, [15] RFLAGS, [16] RIP, [17] user RSP
alarm_tick uint32_t alarm(2) deadline in ticks. 0 = none
stop_sig uint32_t Signal that stopped us (SIGTSTP/SIGSTOP). 0 = not stopped
stopped_reported uint32_t 1 = this stop was already reported to waitpid(WUNTRACED)

NSIG is 32, because the pending/mask sets are uint32_t bitmaps.

Memory mappings and cwd

Field Type Meaning
mmap_vmas[PROC_MAX_VMAS] vma_t Anonymous and file-backed mappings
mmap_next uint64_t Next mapping base; bumps per mapping
cwd[MAX_PATH] char Absolute, normalised. Empty is treated as /
tty_raw uint32_t 0 = canonical, 1 = raw. Not inherited on fork; reset by execve

PROC_MAX_VMAS is 16, MAX_PATH is 256.

Links

Field Type Meaning
next process_t* Table chaining
parent process_t*
children process_t*

vma_t

One mmap region.

Field Type Meaning
file_buf uint8_t* Snapshot buffer for a file-backed mapping; NULL if anonymous
file_size uint32_t Bytes in file_buf

Plus the base, length and protection bits the fault handler consults. Faulting inside a VMA yields a fresh zeroed page with the VMA's prot, or a copy of the corresponding slice of file_buf.

file_buf is deep-copied on fork and freed on munmap, execve and reap. Partial munmap and mprotect split the VMA.

vfs_node_t

A VFS inode. Pool size is MAX_INODES (512, raised from 256 at v6.4.197) in kernel/fs/vfs.c.

Field Type Meaning
open_refs uint32_t 1 after open, +1 per dup, −1 per close; released at zero
orphaned uint8_t Unlinked from the tree while still open; freed at last close
on_free_list uint8_t Already queued in free_nodes[] — double-free guard
mpath[MAX_NAME] char Path within the mount, e.g. /foo.txt
mount_ent void* mount_entry_t* to flush writes through
dev_type uint32_t 0 = regular file, else a DEV_* special
proc_type uint32_t 0 = not /proc, else a PROC_* generated node
proc_pid uint32_t For PROC_PID_* nodes: which process this reflects

Important

A VFS fd is a node pointer. The pool must not recycle a node while anyone still holds one, or the next alloc_node() hands the same memory to a different file. open_refs counts every node kind, not just mount mirrors — that narrower version let /proc nodes and unlinked ramdisk files be recycled out from under their holders.

dev_type values

Constant Value Behaviour
DEV_NULL 1 Reads → EOF, writes discarded
DEV_ZERO 2 Reads → endless zero bytes
DEV_RANDOM 3 Reads → pseudo-random bytes (also backs /dev/urandom)

proc_type values

Constant Value Generated content
PROC_MEMINFO 1 MemTotal / MemUsed / MemFree
PROC_UPTIME 2 Seconds since boot
PROC_VERSION 3 Kernel version banner
PROC_CPUINFO 4 Architecture and CPU summary
PROC_PID_DIR 5 /proc/<pid> directory
PROC_PID_STATUS 6 /proc/<pid>/status
PROC_PID_CMDLINE 7 /proc/<pid>/cmdline
PROC_PID_MAPS 8 /proc/<pid>/maps

Content is synthesized on read in vfs_pread — nothing is stored in ino->data. proc_sync() creates and removes the per-pid directories to track the process table.

window_t

A compositor window (kernel/gui/core/compositor.h). Up to MAX_WINDOWS (32).

Geometry

Field Type Meaning
x, y int Current position
w, h uint32_t Current size
normal_x/y/w/h Geometry to restore from maximised or snapped
state int Normal, minimised, maximised, or a snap state
workspace int 0…WORKSPACE_COUNT−1
z_order int Stacking order
visible, focused int
id int Handle for window_destroy, window_focus, …

Note

Maximised and snapped windows are defined by the screen, so their rects are re-derived on a resolution change rather than restored from stale coordinates. Snap states form a two-axis grid — a horizontal side plus a vertical zone — which is what gives quarter tiling.

Interaction state

Field Meaning
dragging, drag_off_x/y Move in progress
resizing, resize_dir, resize_start_* Resize in progress
has_close, has_min, has_max Which title-bar buttons are shown

Callbacks

Field Signature When
draw (win, cx, cy, cw, ch) Every repaint; receives the client rect
on_key (win, key) Key while focused
on_click (win, mx, my, btn) Button release
on_pressed (win, mx, my, btn) Button press
on_mousemove (win, mx, my, btns) Pointer motion
on_tick (win) → int ~30 fps; return 1 if a repaint is needed
reserved void* Per-instance application context

See HOWTO-Add-a-GUI-application.

cpu_info_t

Per-CPU state (kernel/core/smp.h). Up to MAX_CPUS (8).

Field Type Meaning
apic_id uint32_t Assigned by the BSP
apic_id_self uint32_t Read by the core itself via CPUID
cpu_number uint32_t Index into cpu_info[]
stack_base / stack_top uint64_t This core's kernel stack
started volatile int Bringup completed
running volatile int Currently executing

cpu_self() resolves the running core from CPUID(1).EBX[31:24] — an instruction rather than a memory access, so it is valid before the LAPIC mapping is reachable and safe from inside an interrupt.

tss_entry_t

The x86_64 Task State Segment, one per core.

Offset Field Meaning
4 rsp0 Ring-0 stack; the scheduler updates this per task
36 ist1 IST1 — double fault
44 ist2 IST2 — NMI
52–84 ist3ist7 Unused
102 iomap_base Struct is 104 bytes total

Warning

Intel SDM Vol. 3, Fig. 7-11 specifies exactly eight reserved bytes after rsp2. Carrying three dwords there — a leftover of the 32-bit SS0/SS1/SS2 fields — shifts every IST slot four bytes early, so tss_set_ist() writes IST1 at offset 40 while the CPU reads it from 36. The double-fault handler then runs on a garbage stack and triple-faults. The IST mechanism never worked until this was found.

IST stacks are IST_STACK_SIZE (8192) bytes and are allocated per core, so a fault on one core cannot scribble on another's exception stack.

Shared kernel/userspace records

These are copied verbatim across the syscall boundary. Field order must match the kernel's fill order in kernel/core/syscall.c.

Struct Size Defined in
nyx_dirent_t 68 B — char name[64] + uint32_t type user/syscall.h
nyx_procinfo_t 48 B — pid, ppid, state, cpu_time, char comm[32] user/syscall.h
nyx_tm 6 × intsec, min, hour, mday, mon, year user/syscall.h
struct stat 3 × uint32_tst_size, st_mode, st_ino user/syscall.h
struct pollfd int fd; short events; short revents user/syscall.h
struct timeval long tv_sec; long tv_usec user/syscall.h
struct timespec long tv_sec; long tv_nsec user/syscall.h

In nyx_procinfo_t, state is the PROC_* value and cpu_time is accumulated ticks. In nyx_dirent_t, type is 1 for a directory and otherwise a regular file. nyx_tm.mon is 1–12 and year is the full four-digit year.

Capacity summary

Constant Value Defined in
MAX_PROCESSES 512 kernel.h
MAX_THREADS 1024 kernel.h
MAX_FILES 256 kernel.h
PROC_MAX_FDS 32 kernel.h
PROC_MAX_VMAS 16 kernel.h
NSIG 32 kernel.h
MAX_PATH 256 kernel.h
MAX_FILENAME 128 kernel.h
MAX_MOUNTS 16 kernel.h
SYS_TABLE_SIZE 256 kernel.h
MAX_INODES 512 vfs.c
MAX_WINDOWS 32 compositor.h
WORKSPACE_COUNT 4 compositor.h
MAX_CPUS 8 smp.h
TCP_MAX_CONNS 32 tcp.h
MAX_SOCKETS 32 net.c
SLAB_MAX_OBJ 1024 slab.h
IST_STACK_SIZE 8192 kernel.h

See also

External resources

Clone this wiki locally