# Syscalls This project's first principle (project guideline #6): the kernel is the API. This document is the map of every syscall nulsl-libc touches, how errors travel, and how to add the next one. ## The one and only ABI surface `src/syscall.c` — the only file that executes the `syscall` instruction. ``` long syscall(long number, ...); ``` - Arguments 1-6 map to the platform's syscall argument registers. - On success the kernel return value is returned as-is. - On error the Linux kernel returns `-errno` (range `-1..-4095`). `syscall()` translates it: `errno = -ret; return -1;` — the standard libc convention. - Numbers live in `include/sys/syscall.h` as `SYS_*` macros, `#ifndef`-guarded so kernel UAPI headers can coexist. ## The syscalls we use x86_64 Linux ABI: | Number | Name | Used by | Status | |--------|-----------------|----------------------------------|----------| | 0 | read | `read()` | wrapped | | 1 | write | `write()`, `puts()`, `putchar()` | wrapped | | 2 | open | — | constant | | 3 | close | `close()` | wrapped | | 39 | getpid | `getpid()`, bench_syscall | wrapped | | 60 | exit | `_exit()`, `exit()`, `abort()` | wrapped | | 87 | unlink | — (stub uses errno = ENOSYS) | constant | | 228 | clock_gettime | benchmarks only | constant | "Wrapped" means there is a public function in `src/` that calls it. "Constant" means the number is defined in the header but nothing wraps it yet (benchmarks call it directly through `syscall()`). ## Adding a new syscall wrapper 1. Add the number to `include/sys/syscall.h` (guarded, with the ABI it belongs to in a comment). 2. Add the public declaration to the right header (`include/unistd.h` for POSIX stuff, `include/stdio.h` for stdio, ...). 3. Implement it in the matching `src/` file as a thin wrapper: ```c ssize_t write(int fd, const void *buf, size_t count) { return (ssize_t)syscall(SYS_write, fd, buf, count); } ``` If the syscall is not implemented yet, follow the stub convention instead (return the documented error value, `errno = ENOSYS`, `/* TODO */` comment naming what it needs). 4. Update this table. 5. Add or extend a smoke test in `tests/` — if nothing exercises it, it does not exist. ## Porting to a new architecture - `src/syscall.c` — add the register mapping for the new ABI (`#error` otherwise). - `src/crt/crt0.S` — add `_start` for the new ABI. - `include/sys/syscall.h` — the numbers are per-architecture; split the table or move it to `src/arch/` once a second target exists. - `configure.ac` — extend the `host_cpu` case. The project targets Linux on x86_64 today; everything above is written so a second port is a contained, reviewable change.