SchOS/.claude/memory/schunix-sockets-and-evdev.md
Nexoniarz a1c965da1e include: one folder per subsystem, and includes that name it
Sixty-five headers sat side by side in include/, so `#include "irq.h"`
said nothing about where irq.h was or what it belonged to, and errno.h,
stat.h and fcntl.h at the top shadowed the system's for any host tool
built with -I./include. They are in folders now -- arch/ core/ fs/
dev/ gfx/ net/ uapi/ (and ldls/ for the Linux driver layer) -- and
every include names the folder, as Linux's do: "core/proc.h".

Done mechanically and checked the hard way: the kernel built from this
tree disassembles identically to the one built from the tree before
it. The full image boots, and userland is the same set of programs.
Paths in docs and comments follow; docs/guides/layout.md has a table
of what is where, and tools/fix-includes.py rewrites old-style
includes from the folders in the tree, for code written before this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
2026-10-23 15:05:12 +02:00

2.7 KiB

name description metadata
schunix-sockets-and-evdev Unix domain sockets and /dev/input evdev both work; the one lock rule, the names-not-in-the-VFS tradeoff, and where the syscall numbers went
node_type type originSessionId modified
memory project 9d8a2aef-bcf0-47a0-96c6-f706efab4a95 2026-08-05T07:12:20.950Z

Unix domain sockets (kernel/net/unix.c, include/net/socket.h, kernel/sys/sys_net.c) and raw input events (kernel/dev/input.c, include/dev/input.h) are both done and verified — tools\bootcheck.ps1 -Sock and -Evdev.

One lock for the whole socket table, deliberately. A pipe gets a lock per pipe because every operation touches one object; a socket operation touches two, and per-socket locks need an ordering rule every path obeys or they deadlock. Worse, a reader testing peer_closed under its own lock while the closer sets it under the peer's has no interlock and sleeps through its own wakeup. Don't "optimise" this into per-socket locks.

Socket names live in a table, not the filesystem. ls -l /tmp/schcom will not show an s and unlink() of a socket path returns ENOENT. Fixing it properly means a new inode type through both filesystems, iget, dirlookup and stat — a VFS change, not a socket change. Everything that matters works.

connect() deliberately does not wait for accept(). A queued connection is already established on Unix; blocking would deadlock any server that connects to itself.

The syscalls had real Linux numbers assigned (41/49/50/43/42 and friends). They were NO_LINUX stubs before, which meant a musl program calling socket() got "bad syscall" from the ABI translation and never reached the stub at all — same trap as schunix-shm-and-mmap. shutdown is registered as sockshutdown because Schunix already has a native shutdown that powers the machine off.

evdev: /dev/input/event0 (keyboard) and event1 (mouse), major 7, Linux struct input_event layout. Fed by the PS/2 keyboard, the PS/2 mouse and USB HID. The console keeps its own path — both consumers see every key, so keys pressed during a test also land on the shell's input line.

Two things that are not obvious:

  • Below 0x54 a Linux keycode is the AT set-1 scancode, so the PS/2 path needs no table. USB HID does need one (hid_keycode[]), because HID numbers keys by position and the AT set numbers them by matrix wiring order.
  • A full event ring drops the oldest event. Dropping the newest is the obvious choice and it is wrong: the event most likely lost is a key release, and a lost release leaves the key held down forever.

See also schunix-console-tty, schunix-framebuffer-device, schunix-verify-by-driving-shell.