--- name: schunix-shm-and-mmap description: Shared memory and file-backed mmap work now; the rule is that pages a process does not own must never reach kfree metadata: node_type: memory type: project originSessionId: a665e14b-86bd-4b41-a228-51377f3e9225 modified: 2026-08-04T18:45:47.215Z --- **Shared memory and file-backed mmap were implemented on 2026-08-04**, in `kernel/sys/sys_mem.c`. These were the two syscall gaps blocking a display server: without shm, every frame is a copy through a pipe. - `shmget`/`shmat`/`shmdt` — up to 16 segments of 2 MB. Pages are allocated up front and zeroed (a fresh segment handing out the last tenant's bytes would leak them between processes). A segment lives until its last attachment goes. **Their table.inc entries were `NO_LINUX`**, so a musl-linked program never reached them at all; they now carry Linux's numbers (29/30/67). - `mmap` of a regular file reads the contents in. It used to silently return zeroed anonymous pages -- success-shaped, and wrong. **Writable `MAP_SHARED` on a file returns `-ENODEV`** rather than faking it: its whole contract is that stores reach the file, and there is no page cache that could make that true. **The rule that matters: pages a process does not own must never reach kfree().** Three places had to learn it, and each was a real hazard: - `vm_unmap_range()` kfree's everything it unmaps. Use `vm_unmap_norelease()` for device memory and shared segments. - `freevm()` frees any mapped page below `PHYSTOP`. The framebuffer survived only by accident (0xfd000000 is above PHYSTOP); shm pages are kalloc'd and sit below it. `proc_release_shared()` runs before freevm in both `exit()` and `exec()` -- and in exec it must run **before** the `memset(proc->vma)`, which erases the record of which mappings were shared. - `fork()` must map the *same* physical pages and bump the attachment count. `copy_vma_range()`'s share branch now copies the parent's PTEs rather than special-casing the framebuffer address. `struct vma`'s `is_fb` became `no_free` + `shmid` for this reason. **Test with `shmtest`** (`cmd/shmtest`, nine checks) — it forks and has the child write where the parent reads, which is the only convincing proof. Run via `pwsh -File tools/bootcheck.ps1 -Tty`. Still missing for a GUI: raw keyboard/mouse events that bypass the tty line discipline, and unix domain sockets (`socket()` is still a NO_LINUX stub). See [[schunix-console-tty]] and [[schunix-framebuffer-device]].