-
-
Notifications
You must be signed in to change notification settings - Fork 5
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
The process table entry. One per task — kernel thread, user process, or CLONE_VM thread. Table size is MAX_PROCESSES (512).
| 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
|
| 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.
| 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
|
| 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.
| 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
|
| 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.
| 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.
| 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.
| 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.
| Field | Type | Meaning |
|---|---|---|
next |
process_t* |
Table chaining |
parent |
process_t* |
|
children |
process_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.
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.
| 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) |
| 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.
A compositor window (kernel/gui/core/compositor.h). Up to MAX_WINDOWS (32).
| 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.
| 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 |
| 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.
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.
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 |
ist3…ist7
|
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.
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 × int — sec, min, hour, mday, mon, year
|
user/syscall.h |
struct stat |
3 × uint32_t — st_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.
| 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 |
- Process-Management — how the scheduler uses these fields
- Memory-Management — VMAs, page tables and the fault handler
- Filesystem — the VFS node pool and mount table
- GUI-Subsystem — the compositor
- Syscalls — the shared record layouts
- Intel SDM Vol. 3A, Ch. 7 — Task Management — the TSS layout
- System V AMD64 ABI — struct alignment rules
NyxOS v6.4.363 · GPL v2 · GitHub · uselessalter on Discord · nyxos@inbox.lv
NyxOS Wiki
Getting started
Kernel
Storage & network
Graphics & apps
Userspace
HOWTO
- HOWTO-Add-a-system-call
- HOWTO-Write-a-userspace-program
- HOWTO-Add-a-shell-command
- HOWTO-Add-a-GUI-application
Reference
- Syscall-Reference
- Command-Reference
- Hardware-Reference
- Format-Reference
- Kernel-Data-Structures
- Source-Tree-Reference
Project