Skip to content

Syscalls

Userspace enters the kernel through SYSCALL, and the kernel returns through SYSRET. There is no interrupt gate for system calls and no argument block on the stack: the call number goes in rax, and up to six arguments go in registers.

Register Carries
rax the call number on the way in, the result on the way out
rdi, rsi, rdx, r10, r8, r9 arguments one through six
rcx, r11 clobbered by the instruction itself: return address and RFLAGS

The fourth argument is in r10 rather than rcx for the reason the last row gives: SYSCALL puts the return address in rcx before any handler runs, so an argument left there would be gone.

// The whole of the userspace side, from programs/edos_lib/src/sys.rs.
pub unsafe fn syscall2(num: u64, arg1: u64, arg2: u64) -> u64 {
let ret: u64;
unsafe {
asm!(
"syscall",
in("rax") num,
in("rdi") arg1,
in("rsi") arg2,
lateout("rax") ret,
lateout("rcx") _,
lateout("r11") _,
options(nostack),
);
}
ret
}

There is no errno global and no negative-value convention shared across the table. A call that returns a u64 signals failure with u64::MAX; one that returns a signed value signals it with -1. Either way the number itself carries no detail, so the failing handler stores a code on the calling thread and userspace reads it back with call 0x400.

The code is per thread, and every handler that can fail clears it before doing any work, so a stale value from an earlier call cannot be mistaken for a fresh one. A call that succeeds leaves it cleared.

Paths are NUL-terminated and are rejected past 1024 bytes. Every pointer userspace hands over is copied through checked helpers rather than dereferenced: a bad address is EFAULT, not a kernel fault.

124 calls

  1. 0readRead from a descriptor into a user buffer, advancing its offset.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*mut u8Destination buffer.
    rdxcountusizeBytes to read.
    Returnsi64 — bytes read, 0 at end of file, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Blocks on a pipe, a pty or a tty with nothing buffered. Files are served from the page cache, so a hit never reaches the disk.

  2. 1writeWrite a user buffer to a descriptor.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*const u8Source buffer.
    rdxcountusizeBytes to write.
    Returnsu64 — bytes written, u64::MAX on error
    Errors

    A zero-length write returns 0 without touching the descriptor.

  3. 3closeRelease a descriptor.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    Returnsi32 — 0 on success, -1 on error
    Errors
  4. 4list_dirPack a directory listing into a user buffer.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Directory to list.
    rsibuf*mut u8Destination buffer.
    rdxbuf_sizeusizeBuffer capacity in bytes.
    Returnsi64 — bytes written, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Entries are fixed-size headers each followed by a name; the return value is a byte count, not an entry count.

  5. 5getcwdCopy the working directory out as a NUL-terminated path.Filesystem
    RegArgumentTypeMeaning
    rdibuf*mut u8Destination buffer.
    rsisizeusizeBuffer capacity in bytes.
    Returnsi64 — bytes written including the NUL, -1 on error
    Errors
  6. 6chdirChange the working directory of the calling process.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Directory to move to.
    Returnsi64 — 0 on success, -1 on error
    Errors
  7. 7pollWait until one of a set of descriptors is ready.I/O
    RegArgumentTypeMeaning
    rdifds*mut SelectFdArray of descriptors and interests; results are written back in place.
    rsicountusizeNumber of entries.
    rdxtimeout_msu64Timeout in milliseconds.
    Returnsi64 — number of ready descriptors, -1 on error
    Errors

    SelectFd is { fd: u64, interests: PollState, result: PollState }, and PollState is five bools: readable, writable, error, hangup, invalid.

  8. 8fstatMetadata for an open descriptor.Filesystem
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsistatbuf*mut FstatEntryDestination struct.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  9. 9mmapMap anonymous, file-backed or physical memory into the address space.Memory
    RegArgumentTypeMeaning
    rdiaddru64Requested address, or 0 to let the kernel choose.
    rsilengthu64Length in bytes.
    rdxprotu32PROT_READ 0x1, PROT_WRITE 0x2, PROT_EXEC 0x4.
    r10flagsu32MAP_SHARED 0x01, MAP_PRIVATE 0x02, MAP_FIXED 0x10, MAP_ANONYMOUS 0x20, MAP_PHYSICAL 0x40, MAP_WRITE_COMBINING 0x80.
    r8phys_or_fdu64Physical address for MAP_PHYSICAL, descriptor for a file-backed mapping.
    r9file_offsetu64Offset into the file; file-backed mappings only.
    Returnsu64 — mapping address, u64::MAX on error
    Errors

    Pages are faulted in on demand. MAP_PHYSICAL is how a driver in userspace reaches device memory, and it is the reason this call can return EPERM.

  10. 10statMetadata for a path.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Path to inspect.
    rsipath_lenusizeLength of the path in bytes.
    rdxstatbuf*mut FstatEntryDestination struct.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  11. 11munmapRemove a mapping and shoot down the stale TLB entries.Memory
    RegArgumentTypeMeaning
    rdiaddru64Start of the mapping.
    rsilengthu64Length in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errors
  12. 12lseekMove the offset of a file descriptor.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsioffseti64Signed displacement.
    rdxwhenceu320 SEEK_SET, 1 SEEK_CUR, 2 SEEK_END.
    Returnsi64 — the new offset, -1 on error
    Errors

    Only regular files carry an offset; anything else is rejected.

  13. 13ftruncateSet the length of an open file.Filesystem
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsisizeu64New length in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errors
  14. 14fsyncFlush one file, data and metadata, to stable storage.Filesystem
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  15. 15isattyReport whether a descriptor is a terminal.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    Returnsu64 — 1 for a terminal, 0 otherwise
    ErrorsCannot fail.
  16. 16ioctlDevice-specific control, for ptys and for devfs nodes.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsirequestu64Device-defined request code.
    rdxargu64Inline value, or a pointer when arg_len is non-zero.
    r10arg_lenusizeSize of the buffer arg points at.
    r8flagsu64IOCTL_FLAG_READ 1 copies the buffer in, IOCTL_FLAG_WRITE 2 copies it back out.
    Returnsi64 — the device’s own value, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    The buffer is bounced through the kernel rather than handed to the driver, so a device never touches a user pointer. devfs nodes are dispatched directly instead of through the filesystem mailbox.

  17. 17preadRead at an explicit offset, leaving the descriptor offset alone.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*mut u8Destination buffer.
    rdxcountusizeBytes to read.
    r10offsetu64Absolute file offset.
    Returnsi64 — bytes read, 0 at end of file, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Threads of one process share a descriptor table, so they share one offset per descriptor: lseek followed by read races by construction. This call is the fix, and it is ESPIPE on anything without an offset.

  18. 18pwriteWrite at an explicit offset, leaving the descriptor offset alone.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*const u8Source buffer.
    rdxcountusizeBytes to write.
    r10offsetu64Absolute file offset.
    Returnsi64 — bytes written, -1 on error
    Errors

    O_APPEND is deliberately not consulted: a positional write that silently lands somewhere else is worse than no call at all.

  19. 19readvRead into a list of buffers, filling each before moving to the next.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiiov*const IoVecArray of { base, len } pairs.
    rdxiovcntusizeNumber of entries, at most IOV_MAX (1024).
    Returnsi64 — total bytes read, 0 at end of file, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Each buffer is a separate underlying read, so the buffers fill in order but the sequence is not atomic against a concurrent reader. A short read ends the sequence, and an error after a partial transfer returns the partial count with errno cleared, as POSIX requires.

  20. 20writevWrite a list of buffers in order.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiiov*const IoVecArray of { base, len } pairs.
    rdxiovcntusizeNumber of entries, at most IOV_MAX (1024).
    Returnsi64 — total bytes written, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    A zero-length entry is skipped rather than ending the run. A total length past i64::MAX is rejected before anything is written.

  21. 21accessTest a path for existence and readability.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Path, not NUL-terminated.
    rsipath_lenusizeLength in bytes.
    rdxmodeu32F_OK 0, X_OK 1, W_OK 2, R_OK 4.
    Returnsi32 — 0 if the access would be permitted, -1 otherwise
    Errorsplus any filesystem failure, mapped from FsError

    Delegates to faccessat with AT_FDCWD. There is one user id, so only the read-only attribute can actually deny anything; undefined mode bits are EINVAL rather than ignored.

  22. 22pipeCreate a pipe and return both ends.I/O
    RegArgumentTypeMeaning
    rdipipefd*mut [u64; 2]Receives [read_fd, write_fd].
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    If the copy back to userspace faults, both descriptors are closed rather than leaked.

  23. 32dupDuplicate a descriptor onto the lowest free number.I/O
    RegArgumentTypeMeaning
    rdioldfdu64Descriptor to duplicate.
    Returnsu64 — the new descriptor, u64::MAX on error
    Errors
  24. 33dup2Duplicate a descriptor onto a chosen number, closing whatever was there.I/O
    RegArgumentTypeMeaning
    rdioldfdu64Descriptor to duplicate.
    rsinewfdu64Target number.
    Returnsu64 — newfd, u64::MAX on error
    Errors
  25. 34msyncFlush the dirty pages of a MAP_SHARED range to storage.Memory
    RegArgumentTypeMeaning
    rdiaddru64Start of the range.
    rsilenu64Length in bytes.
    rdxflagsu32MS_ASYNC 0x1, MS_SYNC 0x2, MS_INVALIDATE 0x4.
    Returnsi64 — 0 on success, -1 on error
    Errors

    The VMA lock collects the work and is dropped before any disk I/O runs.

  26. 35nanosleepSleep for a duration given in nanoseconds.Time
    RegArgumentTypeMeaning
    rdireq*const TimespecRequested duration; tv_nsec must be under 1e9.
    rsirem*mut TimespecAccepted and validated, never written.
    Returnsi32 — 0 on success, -1 on error
    Errors

    A sleep ends on any wake, so the kernel loops until the deadline passes. `rem` stays unwritten because there are no userspace signal handlers yet, which makes an early return unobservable.

  27. 39getpidProcess ID of the caller.Process

    Takes no arguments.

    Returnsu64 — the pid
    ErrorsCannot fail.
  28. 40waitpidWait for a child to exit and collect its status.Process
    RegArgumentTypeMeaning
    rdipidu64Child to wait for.
    rsiblocku641 parks until the child exits, anything else polls.
    rdxstatus*mut i32Receives the exit code; may be null.
    Returnsu64 — the pid, 0 if it has not exited and block was 0, u64::MAX on error
    Errors
  29. 57spawnLoad a program as a new process with three inherited descriptors.Process
    RegArgumentTypeMeaning
    rdipath*const u8Program to load.
    rsiargv*const *const u8NULL-terminated argument vector.
    rdxstdin_fdu64Descriptor to install as stdin.
    r10stdout_fdu64Descriptor to install as stdout.
    r8stderr_fdu64Descriptor to install as stderr.
    Returnsu64 — the child pid, u64::MAX on error
    Errors

    Registers are scarce, so anything richer than three descriptors goes through spawn2.

  30. 59execveReplace this process’s image, keeping its pid.Process
    RegArgumentTypeMeaning
    rdipath*const u8Program to load.
    rsiargv*const *const u8NULL-terminated argument vector.
    rdxenvp*const *const u8NULL-terminated environment.
    Returnsdoes not return on success; u64::MAX on error
    Errors

    One rule dictates the order of the whole implementation: nothing observable changes until the point of no return, and nothing after that point may fail.

  31. 60exitTerminate the calling thread.Process
    RegArgumentTypeMeaning
    rdicodei32Exit status.
    Returnsdoes not return
    ErrorsCannot fail.
  32. 72fcntlDescriptor flags, status flags and duplication.I/O
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsicmdu64F_DUPFD 0, F_GETFD 1, F_SETFD 2, F_GETFL 3, F_SETFL 4, F_DUPFD_CLOEXEC 1030.
    rdxargu64Command-specific argument.
    Returnsi64 — command-specific, -1 on error
    Errors

    F_GETFL reports the access mode, O_APPEND and O_NONBLOCK. F_SETFL can change only O_NONBLOCK; the access mode and the creation flags are ignored there rather than refused, so a caller that reads flags and writes them back does not fail.

  33. 76truncateSet a file length by path.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Path, not NUL-terminated.
    rsipath_lenusizeLength in bytes.
    rdxsizeu64New length in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Growing a file creates a hole: the blocks it names are never allocated and read back as zeros. Shrinking zeroes the surviving tail of the last cached page, so a later grow cannot resurrect the old bytes.

  34. 78getdentsStream a directory listing from an entry index.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Directory to list.
    rsipath_lenusizeLength in bytes.
    rdxbuf*mut u8Destination buffer.
    r10buf_sizeusizeBuffer capacity in bytes.
    r8startusizeIndex of the first entry to pack.
    Returnsi64 — bytes written, 0 once `start` is past the last entry, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    The caller advances `start` by the number of entries it decoded, so there is no in/out cursor to keep. An entry that cannot fit on its own is EINVAL, not 0, because 0 means end of directory and would silently drop the tail.

  35. 82renameRename or move an entry.Filesystem
    RegArgumentTypeMeaning
    rdiold_path*const u8Existing path.
    rsinew_path*const u8Destination path.
    Returnsi32 — 0 on success, -1 on error
    Errors
  36. 102getuidReal user id of the calling process.System

    Takes no arguments.

    Returnsu64 — the uid
    ErrorsCannot fail.
  37. 104getgidReal group id of the calling process.System

    Takes no arguments.

    Returnsu64 — the gid
    ErrorsCannot fail.
  38. 109setpgidPlace a process in a process group.Process
    RegArgumentTypeMeaning
    rdipidu64The process to move; 0 means the caller.
    rsipgidu64The group to join; 0 means lead a new group of its own.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    How a shell puts each pipeline in a group of its own: the first stage leads with a pgid of 0 and the rest join it. That group is then what the terminal hands Ctrl+C and Ctrl+Z to, which is why killing a pipeline kills every stage rather than only the one the shell named.

  39. 121getpgidThe process group a process belongs to.Process
    RegArgumentTypeMeaning
    rdipidu64The process to ask about; 0 means the caller.
    Returnsu64 — the group id, or u64::MAX on error
    Errors
  40. 162syncFlush every dirty block cache page to disk.Filesystem

    Takes no arguments.

    Returnsu64 — always 0
    ErrorsCannot fail.

    Errors are the writeback thread’s to log; the caller is told nothing because it can do nothing.

  41. 169rebootSync every filesystem, then stop or restart the machine.System
    RegArgumentTypeMeaning
    rdicmdu640 power off, 1 reset, 2 halt.
    Returnsdoes not return on success; -1 on error
    Errors

    Soft-off with no AML interpreter: PM1a/PM1b_CNT come from the FADT and SLP_TYPa is decoded structurally out of the DSDT’s \_S5_ package, with emulator ports as a fallback. Reset drives RST_CNT then pulses the 8042. Progress prints to the serial port rather than the log ring, because the kthread that drains the ring will not run again.

  42. 186gettidThread ID of the caller.Process

    Takes no arguments.

    Returnsu64 — the tid, 0 when no thread is current
    ErrorsCannot fail.

    The same value as `getpid` only when the process has one thread. `futex_wait_pi` names an owner by tid, so a userspace lock that lends priority reads it here.

  43. 202mountMount a partition at a path.Filesystem
    RegArgumentTypeMeaning
    rdidevice_idu64Block device index.
    rsipartition_idxu64Partition within that device.
    rdxpath*const u8Mount point.
    r10fs_type*const u8Filesystem name, e.g. efs or fat32.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  44. 203list_partitionsDescribe every partition the kernel enumerated, as text.Filesystem
    RegArgumentTypeMeaning
    rdibuf*mut u8Destination buffer.
    rsisizeu64Buffer capacity in bytes.
    Returnsi64 — bytes written, -1 on error
    Errors
  45. 204mkdirCreate a directory.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Directory to create.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  46. 205rmdirRemove an empty directory.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Directory to remove.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError
  47. 206rmdir_allRemove a directory and everything under it.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Root of the subtree to remove.
    Returnsi64 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    The recursion lives in the kernel because a userspace walk would race with anyone else writing into the tree.

  48. 208list_mountsDescribe the mount table as text.Filesystem
    RegArgumentTypeMeaning
    rdibuf*mut u8Destination buffer.
    rsisizeusizeBuffer capacity in bytes.
    Returnsi64 — bytes written, -1 on error
    Errors
  49. 209sleep_msPark the calling thread for a duration.Time
    RegArgumentTypeMeaning
    rdimillisecondsu64How long to sleep.
    Returnsu64 — always 0
    ErrorsCannot fail.
  50. 210monotonic_timeNanoseconds since boot, from the HPET.Time

    Takes no arguments.

    Returnsu64 — nanoseconds
    ErrorsCannot fail.

    Monotonic with microsecond resolution, scaled to nanoseconds. It never goes backwards and never jumps with the wall clock.

  51. 211cloneStart a thread in the calling process’s address space.Process
    RegArgumentTypeMeaning
    rdifuncu64Entry point.
    rsiargu64Value passed to the entry point.
    rdxflagsu64Clone flags.
    r10child_stacku64Top of the stack the child runs on.
    Returnsu64 — the child thread id, u64::MAX on error
    Errors

    The child shares the address space, the descriptor table and the heap break, and gets its own TLS block and stack.

  52. 212futex_waitSleep while a word in memory still holds an expected value.Sync
    RegArgumentTypeMeaning
    rdiaddr*const u32Word to watch.
    rsiexpectedu32Value to sleep on.
    rdxtimeout_nsu64Timeout in nanoseconds; u64::MAX waits forever.
    Returnsu64 — 0 woken with the value changed, 1 value did not match or a spurious wake, 2 timed out, u64::MAX on error
    Errors

    Keyed by the address space plus the address, so two processes sharing a mapping share a queue. The wait queue is dropped when its last waiter leaves.

  53. 213futex_wakeWake waiters parked on a word.Sync
    RegArgumentTypeMeaning
    rdiaddr*const u32Word waiters are parked on.
    rsicountu32How many to wake.
    Returnsu64 — waiters actually woken, u64::MAX on error
    Errors
  54. 214getrandomFill a buffer with random bytes.System
    RegArgumentTypeMeaning
    rdibuf*mut u8Destination buffer.
    rsilenusizeBytes to generate, at most 1 MiB.
    rdxflagsu64Must be 0.
    Returnsi64 — bytes written, -1 on error
    Errors
  55. 215shm_createCreate a shared memory region.Shared memory
    RegArgumentTypeMeaning
    rdisizeu64Size in bytes.
    Returnsi64 — the region id, -1 on error
    Errors
  56. 216shm_mapMap a shared region into the calling process.Shared memory
    RegArgumentTypeMeaning
    rdishm_idu64Region id.
    rsiaddr_hintu64Suggested address, or 0 to let the kernel choose.
    rdxprotu64PROT_READ 0x1, PROT_WRITE 0x2, PROT_EXEC 0x4.
    Returnsu64 — the mapping address, u64::MAX on error
    Errors

    This is what a window buffer is: the client draws into the region and the compositor reads the same frames.

  57. 217shm_unmapUnmap a shared region from the calling process.Shared memory
    RegArgumentTypeMeaning
    rdiaddru64Address the region was mapped at.
    Returnsi64 — 0 on success, -1 on error
    Errors
  58. 218shm_destroyDestroy a shared region.Shared memory
    RegArgumentTypeMeaning
    rdishm_idu64Region id.
    Returnsi64 — 0 on success, -1 on error
    Errors

    Refused while any mapping is still live.

  59. 219window_createRegister a window with the kernel.Window
    RegArgumentTypeMeaning
    rdixi64Position, x.
    rsiyi64Position, y.
    rdxwidthu64Width in pixels.
    r10heightu64Height in pixels.
    Returnsu64 — the window id, u64::MAX on error
    Errors

    The kernel owns the registry and routes input to it. Decoration, stacking and everything else people call a window manager is userspace.

  60. 220window_destroyRemove a window from the registry.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  61. 221window_setSet a window property.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    rsipropu64VISIBLE 1, X 2, Y 3, WIDTH 4, HEIGHT 5, TITLE_PTR 6, BUFFER_SHM 7, FLAGS 8.
    rdxvalueu64The value, or a pointer for TITLE_PTR.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    FLAGS carries FLAG_DOCK 1, the undecorated, undraggable window the taskbar uses.

  62. 222window_getRead a window property.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    rsipropu64Property id, as for window_set.
    Returnsu64 — the property value, u64::MAX on error
    Errors
  63. 223window_pollDrain pending events for a window.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    rsievents*mut WindowEventDestination array.
    rdxmaxu64Capacity of that array.
    Returnsu64 — events copied, u64::MAX on error
    Errors
  64. 224window_listList every window, for the compositor.Window
    RegArgumentTypeMeaning
    rdibuf*mut WindowListEntryDestination array.
    rsimaxu64Capacity of that array.
    rdxflagsu64Bit 0 (WINDOW_LIST_CONSUME_DAMAGE) clears each listed window’s damage as it is read.
    Returnsu64 — entries written, u64::MAX on error
    Errors

    Consuming damage in the same call that reports it is what keeps the compositor from redrawing a window twice or missing a repaint: the caller that acts on the damage is the one that takes it. The list is snapshotted under the registry lock and copied out after it is released, because a copy to a user pointer can demand-fault and parking on a page fill under that lock would leave every other CPU spinning behind it.

  65. 225window_send_eventPost an event to a window the caller does not own.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Target window.
    rsievent*const WindowEventEvent to deliver.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    How the window manager asks a client to close itself.

  66. 226clock_gettimeNanoseconds since the Unix epoch.Time
    RegArgumentTypeMeaning
    rdibuf*mut u8Eight-byte buffer receiving a little-endian u64.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    Answered from the monotonic counter plus a wall-clock offset sampled at boot, so it costs a counter read rather than several RTC port round-trips.

  67. 227openptyOpen a pty master and slave pair.I/O
    RegArgumentTypeMeaning
    rdifds*mut [u64; 2]Receives [master_fd, slave_fd].
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    What the terminal emulator opens before it spawns a shell.

  68. 228spawn2Spawn with arguments, an environment and three descriptors.Process
    RegArgumentTypeMeaning
    rdiargs*const SpawnArgsStruct of { path, argv, envp, stdin_fd, stdout_fd, stderr_fd }.
    Returnsu64 — the child pid, u64::MAX on error
    Errors
  69. 229killSend a signal to a process.Process
    RegArgumentTypeMeaning
    rdipidu64Target process.
    rsisignumu32Signal number, 1 to 31.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  70. 230sigactionInstall a signal disposition.Process
    RegArgumentTypeMeaning
    rdisignumu32Signal number, 1 to 31; SIGKILL is rejected.
    rsihandleru320 SIG_DFL, 1 SIG_IGN, otherwise a handler address.
    Returnsu64 — the previous disposition, u64::MAX on error
    Errors
  71. 231shm_sizeSize of a shared region.Shared memory
    RegArgumentTypeMeaning
    rdishm_idu64Region id.
    Returnsi64 — size in bytes, -1 on error
    ErrorsCannot fail.
  72. 232window_damageTell the compositor which part of a window has repainted.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    rsixu32Left edge of the repainted region, in window coordinates.
    rdxyu32Top edge of that region.
    r10wu32Its width. Zero means the whole window.
    r8hu32Its height. Zero means the whole window.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    Only the window’s own process may declare it repainted, or any process could make the compositor redraw the screen every frame. The region is clamped to the window, since one outside it would grow the union the compositor redraws without describing a pixel it can draw. A client that does not track its own damage passes a zero size and gets the whole window.

  73. 233sigprocmaskRead and change the calling thread’s blocked signal mask.Process
    RegArgumentTypeMeaning
    rdihowu32SIG_BLOCK 0, SIG_UNBLOCK 1, SIG_SETMASK 2.
    rsimasku32The set to apply.
    Returnsu64 — the previous mask, u64::MAX on error
    Errors

    Sets are 32 bits, so the mask goes in and the old one comes back by value rather than through pointers, matching sigaction. A signal sent while blocked is recorded pending without killing or waking the target; widening the mask delivers it immediately, and SIGKILL is dropped from the mask rather than making the call fail.

  74. 234window_grant_shellAppoint another process as part of the shell.Window
    RegArgumentTypeMeaning
    rdipidu64Process to appoint.
    Returnsi32 — 0 on success, -1 on error
    Errors

    Moving, resizing, framing, minimizing and posting events to a window belong to a shell, not to the window’s owner, so they cannot be gated on ownership. They are gated on this instead. Only a process that already holds the privilege may grant it, and the kernel seeds exactly one: `bin/edos-init`, the only process it starts, which appoints the compositor and the panel. The grant is per pid, follows a process’s threads, and is dropped when the process exits.

  75. 235trace_ctlStart or stop syscall tracing on a thread.System
    RegArgumentTypeMeaning
    rdiopu64What to do: begin a trace generation, attach a thread, or stop.
    rsiargu64The thread id for an attach; 0 means the caller.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    The control half of what `strace` is built on. Tracing is a per-thread generation counter rather than a flag, so a stale attach from a previous run cannot resurrect itself.

  76. 236trace_readDrain buffered syscall trace records.System
    RegArgumentTypeMeaning
    rdibuf*mut TraceRecordArray receiving the records.
    rsimaxu64How many records the array holds.
    rdxtimeout_msu64How long to wait for at least one record.
    Returnsu64 — records written, or u64::MAX on error
    Errors

    Records carry the call number, not its name: the table in `syscalls/table.rs` is what turns one into the other, and a call added without a row there prints as `syscall_NNN`.

  77. 237tcsetpgrpHand the terminal to a process group.I/O
    RegArgumentTypeMeaning
    rdifdu64A descriptor on either side of the PTY.
    rsipgidu64The group that becomes the foreground job.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    This is what makes a job “foreground”. The line discipline aims Ctrl+C and Ctrl+Z at whichever group holds the terminal, so a shell resuming a job gives it the terminal first and takes it back when the job stops or exits.

  78. 238tcgetpgrpThe process group currently holding the terminal.I/O
    RegArgumentTypeMeaning
    rdifdu64A descriptor on either side of the PTY.
    Returnsu64 — the foreground group id, or u64::MAX on error
    Errors
  79. 239sigreturnReturn from a signal handler.Process

    Takes no arguments.

    Returnsdoes not return
    ErrorsCannot fail.

    Never called directly. The kernel builds a frame on the handler’s stack whose return address points here, so a handler that simply returns lands in this call and the kernel restores the context the signal interrupted.

  80. 240socketCreate a socket and install it in the descriptor table.Network
    RegArgumentTypeMeaning
    rdidomainu64AF_INET 2.
    rsitypeu64SOCK_STREAM 1, SOCK_DGRAM 2.
    rdxprotocolu64Ignored; implied by the type.
    Returnsu64 — the new descriptor, u64::MAX on error
    Errors
  81. 241bindBind a socket to a local address.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiaddr*const SockAddrInLocal address.
    rdxaddr_lenu64Size of that struct.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  82. 242connectOpen a connection to a remote address.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiaddr*const SockAddrInRemote address.
    rdxaddr_lenu64Size of that struct.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    Blocks through the TCP handshake.

  83. 243listenMark a bound socket as accepting connections.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibacklogu32Pending connection queue depth.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  84. 244acceptTake the next established connection off a listening socket.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiaddr*mut SockAddrInReceives the peer address; may be null.
    rdxaddr_len*mut u32In and out length for that struct.
    Returnsu64 — descriptor for the new connection, u64::MAX on error
    Errors
  85. 245sendtoSend on a socket, with an explicit destination for datagrams.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*const u8Payload.
    rdxlenu64Payload length.
    r10flagsu64Unused.
    r8addr*const SockAddrInDestination; null on a connected socket.
    r9addr_lenu64Size of that struct.
    Returnsu64 — bytes sent, u64::MAX on error
    Errors
  86. 246recvfromReceive on a socket, optionally reporting the sender.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsibuf*mut u8Destination buffer.
    rdxlenu64Buffer capacity.
    r10flagsu64Unused.
    r8addr*mut SockAddrInReceives the sender address; may be null.
    r9addr_len*mut u32In and out length for that struct.
    Returnsu64 — bytes received, u64::MAX on error
    Errors
  87. 247shutdownClose one or both directions of a connection.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsihowu640 read, 1 write, 2 both.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  88. 248setsockoptSet a socket option.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsileveli32Option level.
    rdxoptnamei32Option name.
    r10val*const u8Option value.
    r8val_lenu32Length of that value.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  89. 249pingSend an ICMP echo request and wait for the reply.Network
    RegArgumentTypeMeaning
    rdidst_ip*const [u8; 4]Destination address.
    rsiidu16ICMP identifier.
    rdxsequ16ICMP sequence number.
    r10timeout_msu64Timeout in milliseconds; 0 means 5000.
    Returnsu64 — round-trip time in microseconds, u64::MAX on timeout or error
    Errors

    A raw socket API would be the general answer; this is the one ICMP case userspace actually needs.

  90. 250netinfoDescribe the network interfaces as text.Network
    RegArgumentTypeMeaning
    rdibuf*mut u8Destination buffer.
    rsilenusizeBuffer capacity in bytes.
    Returnsu64 — bytes written, u64::MAX on error
    Errors
  91. 251getsockoptRead a socket option.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsileveli32Option level.
    rdxoptnamei32Option name.
    r10val*mut u8Receives the value.
    r8val_len*mut u32In and out length for that buffer.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  92. 252getpeernameAddress of the remote end of a connection.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiaddr*mut SockAddrInReceives the peer address.
    rdxaddr_len*mut u32In and out length for that struct.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  93. 253getsocknameLocal address a socket is bound to.Network
    RegArgumentTypeMeaning
    rdifdu64File descriptor.
    rsiaddr*mut SockAddrInReceives the local address.
    rdxaddr_len*mut u32In and out length for that struct.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors
  94. 254statfsFilesystem statistics for the mount that holds a path.Filesystem
    RegArgumentTypeMeaning
    rdipath*const u8Any path on the filesystem.
    rsibuf*mut RawStatFsDestination struct.
    rdxbuf_lenusizeSize of that struct.
    Returnsi64 — 0 on success, -1 on error
    Errors
  95. 255forkDuplicate the calling process, copy-on-write.Process

    Takes no arguments.

    Returnsi64 — the child pid in the parent, 0 in the child, -1 on error
    Errors

    Private mappings are marked read-only in both processes and split on the first write fault.

  96. 256getdnsThe resolver address the stack learned from DHCP.Network
    RegArgumentTypeMeaning
    rdiaddr*mut [u8; 4]Receives the resolver address.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    A resolver is configuration, and there is no /etc/resolv.conf convention here, so userspace asks the stack that learned it.

  97. 257openatOpen a path resolved against a directory descriptor.I/O
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    r10flagsu64Access mode and creation flags.
    Returnsi64 — new descriptor, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    The only way in: a plain open is this call against AT_FDCWD. The low two bits are the access mode — 0 O_RDONLY, 1 O_WRONLY, 2 O_RDWR — and 0x40 is O_CREAT, 0x200 O_TRUNC, 0x400 O_APPEND, 0x800 O_NONBLOCK. An append offset is resolved per write rather than at open time. Taking pointer and length rather than a NUL-terminated string means userspace does not have to allocate a CString per open.

  98. 258mkdiratCreate a directory relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    No mode argument: there are no permission bits to observe yet.

  99. 262fstatatStat a path resolved against a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    r10statbuf*mut FstatEntryReceives the metadata.
    r8flagsu64Must be zero.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    stat is this call against the cwd. A nonzero flags word is rejected rather than ignored: AT_SYMLINK_NOFOLLOW cannot be honoured while the lookup follows links.

  100. 263unlinkatRemove a file or directory relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    r10flagsu640, or AT_REMOVEDIR (0x200) to remove a directory.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    AT_REMOVEDIR is the only accepted flag; anything else is EINVAL.

  101. 264renameatRename, resolving each side against its own directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdiolddirfdi64Base for the old path, or AT_FDCWD (-100).
    rsioldpath*const u8Existing name.
    rdxoldpath_lenusizeLength in bytes.
    r10newdirfdi64Base for the new path, or AT_FDCWD (-100).
    r8newpath*const u8New name.
    r9newpath_lenusizeLength in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    rename routes through the same body, which is what gives it real filesystem error codes instead of a flat EINVAL.

  102. 266symlinkatCreate a symbolic link relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rditarget*const u8What the link points at, stored verbatim.
    rsitarget_lenusizeLength in bytes.
    rdxnewdirfdi64Base for the link path, or AT_FDCWD (-100).
    r10linkpath*const u8Where the link is created.
    r8linkpath_lenusizeLength in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    The descriptor places the link only. The target is never resolved at creation time, so it may dangle, and a dangling link still takes the name.

  103. 267readlinkatRead a link target relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8The link itself.
    rdxpath_lenusizeLength in bytes.
    r10buf*mut u8Destination buffer.
    r8buf_lenusizeBuffer capacity in bytes.
    Returnsi64 — bytes written, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    readlink is this call against the cwd.

  104. 269faccessatTest access to a path relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    r10modeu32F_OK 0, X_OK 1, W_OK 2, R_OK 4.
    r8flagsu64Must be zero.
    Returnsi32 — 0 if the access would be permitted, -1 otherwise
    Errorsplus any filesystem failure, mapped from FsError

    Flags are rejected rather than ignored. AT_EACCESS names the only set of ids there is, and AT_SYMLINK_NOFOLLOW cannot be honoured while the lookup follows links.

  105. 280utimensatSet a file’s access and modification times.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    r10times*const [Timespec; 2]Access time then modification time; null means both now.
    r8flagsu64Must be zero.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    UTIME_NOW stamps the current time and UTIME_OMIT leaves that field alone. EFS applies both in one journal transaction. AT_SYMLINK_NOFOLLOW is rejected, since the underlying set_times follows links.

  106. 281clock_settimeStep the wall clock to a known time.Time
    RegArgumentTypeMeaning
    rdibuf*const u8Eight-byte buffer holding little-endian nanoseconds since the Unix epoch.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    The RTC is sampled once at boot and every later answer is that reading plus HPET ticks, so the clock is only ever as good as one one-second-resolution sample. `sntp` corrects it through here. The step is stored as an offset, so the monotonic counter durations are measured against is untouched.

  107. 282sched_yieldGive up the rest of this thread’s timeslice.Process

    Takes no arguments.

    Returnsu64 — always 0
    ErrorsCannot fail.

    Cannot fail: the thread stays runnable and is put back on its run queue behind anything else ready at the same priority. With nothing else ready it returns having done nothing but pay the syscall boundary, which is why `switchbench` measures the idle case separately.

  108. 283mkfifoatCreate a named pipe relative to a directory descriptor.Filesystem
    RegArgumentTypeMeaning
    rdidirfdi64Directory the path is resolved against, or AT_FDCWD (-100) for the cwd. Ignored when the path is absolute.
    rsipath*const u8Path, not NUL-terminated.
    rdxpath_lenusizeLength in bytes.
    Returnsi32 — 0 on success, -1 on error
    Errorsplus any filesystem failure, mapped from FsError

    Creates the name only; the pipe behind it is allocated on the first open and freed when the last descriptor closes. No mode argument, for the same reason mkdirat has none.

  109. 284clipboard_getRead a clipboard buffer.Window
    RegArgumentTypeMeaning
    rdiwhichu640 for the clipboard, 1 for the primary selection.
    rsibuffer*mut u8Where to copy the contents. May be null to ask only for the length.
    rdxlenusizeRoom in the buffer, in bytes.
    Returnsu64 — the full length held, which may exceed len
    Errors

    Returns the whole length rather than the number of bytes copied, so a caller with a short buffer learns how big to make it. The copy happens after the clipboard lock is released, for the reason window_list copies outside the registry lock.

  110. 285clipboard_setReplace a clipboard buffer.Window
    RegArgumentTypeMeaning
    rdiwhichu640 for the clipboard, 1 for the primary selection.
    rsibuffer*const u8Contents to store. Ignored when len is 0.
    rdxlenusizeLength in bytes, at most 64 KiB.
    Returnsi32 — 0 on success, -1 on error
    Errors

    The clipboard lives in the kernel so a copy outlives the process that made it: closing the window you copied from does not empty it. A length of 0 clears the buffer and reads no user pointer. The bytes are copied in before the lock is taken, since a copy from a user pointer can demand-fault and parking on a page fill under a spin lock would leave every other CPU spinning behind it.

  111. 286window_waitBlock until a window has events queued or the screen has been presented.Window
    RegArgumentTypeMeaning
    rdiwindow_idu64Window id.
    rsiseen_frameu64The frame count the caller last acted on, taken from a previous return.
    rdxtimeout_msu64Milliseconds to wait, or 0 to wait indefinitely.
    Returnsu64 — reason bits in the low 32 (1 events, 2 frame) and the current frame count in the high 32; 0 if the wait timed out with nothing to report
    ErrorsCannot fail.

    A client with no way to block guesses an interval and sleeps: it either wakes with nothing to do or leaves an event sitting for the rest of that interval. window_poll cannot block, so this exists alongside it rather than replacing it — the caller still polls to collect the events once this says there are some. The frame count is passed back in rather than remembered per window, because a window can be waited on from more than one thread and a kernel-held count would let whichever called first consume the signal.

  112. 287window_presentReport that a frame has been put on the display.Window

    Takes no arguments.

    Returnsu64 — always 0
    ErrorsCannot fail.

    Called by whatever owns the screen, once per presented frame. It wakes every client blocked in window_wait so they draw into the frame after this one instead of guessing when it happened. Deliberately not a side effect of consuming damage: that happens before the frame is drawn, and a client woken then would be racing the compositor it is trying to keep step with.

  113. 288window_grab_keyClaim or release a key chord, so the focused window does not see it.Window
    RegArgumentTypeMeaning
    rdicodeu32pc_keyboard key code.
    rsimodsu32Modifier mask: shift, ctrl, alt.
    rdxclaimu64Non-zero to claim the chord, zero to release it.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    The mask is matched exactly, so Alt+Tab and Ctrl+Alt+Tab are different chords and claiming one leaves the other with the focused window. Restricted to the session shell for the same reason window management is: a chord claimable by any process would let one program read another’s keys by taking them away from it. A grab dies with the process that holds it, like a file descriptor, so there is no reclaim path to get wrong.

  114. 289mprotectChange the protection of an existing mapping.Memory
    RegArgumentTypeMeaning
    rdiaddru64Start of the range; must be page aligned.
    rsilengthu64Length in bytes, rounded up to a page.
    rdxprotu32PROT_READ 0x1, PROT_WRITE 0x2, PROT_EXEC 0x4.
    Returnsi32 — 0 on success, -1 on error
    Errors

    The range is split at both edges so it is a whole number of VMAs, then each is retagged and its page table entries updated. A hole anywhere in the range changes nothing and reports ENOMEM, so a partly applied protection is never observable. A page already marked copy-on-write is not made writable here: the fault path still owns that transition, and dropping the COW bit on a retag would share a private page.

  115. 314sched_setattrSet a thread’s priority and the service it asks for per pick.Process
    RegArgumentTypeMeaning
    rditidu64The thread to change; 0 means the caller.
    rsiattr*const SchedAttru32 priority, u32 padding, u64 slice_ns.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    Both fields are clamped rather than rejected: the priority saturates at the top of the table and the slice is held to MIN_SLICE..=MAX_SLICE, which is 250 us to 10 ms. There is no privilege check because this system has no user model to check against, and EEVDF is what makes that tolerable — the worst a thread can do to another by taking the top of the table is claim about 6x its share, which is a share and not a lockout.

  116. 315sched_getattrRead back a thread’s scheduling attributes.Process
    RegArgumentTypeMeaning
    rditidu64The thread to ask about; 0 means the caller.
    rsiattr*mut SchedAttrFilled in with the current priority and slice.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    Reports what was actually set rather than what was asked for, so a caller learns where its slice landed after the clamp.

  117. 316setdnsPoint the resolver at an address, or clear the override.Network
    RegArgumentTypeMeaning
    rdiaddr*const [u8; 4]Resolver address, or 0.0.0.0 to go back to the one DHCP learned.
    Returnsu64 — 0 on success, u64::MAX on error
    Errors

    This is what lets a caching resolver redirect every program on the machine to itself without any of them being rebuilt: they already ask `getdns` for the address to query. The override is held against the calling thread and dies with it.

  118. 317futex_wait_pi`futex_wait`, plus the thread the caller believes holds the lock.Sync
    RegArgumentTypeMeaning
    rdiaddr*const u32Word to watch.
    rsiexpectedu32Value to sleep on.
    rdxtimeout_nsu64Timeout in nanoseconds; u64::MAX waits forever.
    r10owner_tidu64Thread believed to hold the word, or 0 to ask for no lending.
    Returnsu64 — as futex_wait: 0 woken with the value changed, 1 no match or a spurious wake, 2 timed out, u64::MAX on error
    Errors

    A futex word is opaque to the kernel, so unlike a blocking mutex there is nothing in it to read an owner out of; the waiter names one and the kernel lends its priority for exactly as long as the wait lasts. The loan ends with the wait rather than with the release, because the release is a userspace store the kernel never sees.

  119. 318profile_ctlStart, stop, or report on the sampling profiler.System
    RegArgumentTypeMeaning
    rdiopu64START, STOP or STATS.
    rsiargu64The requested period for START, or a *mut Stats for STATS.
    Returnsu64 — for START the period actually in force, otherwise 0; u64::MAX on error
    Errors

    One session at a time, owned by the thread that started it, so only that thread may stop it or drain samples. The period comes back clamped to what the sampler accepts rather than being refused.

  120. 319profile_readDrain samples from the running session.System
    RegArgumentTypeMeaning
    rdidst*mut SampleDestination buffer.
    rsimaxu64How many samples to take, clamped to the batch limit.
    rdxtimeout_msu64Park for this long if none are waiting; 0 does not wait.
    Returnsu64 — samples written, 0 on timeout, u64::MAX on error
    Errors

    The session owner’s alone. Anyone else draining would take samples the profiler then never sees, and anyone else parking would add a second waiter to a queue that is kept at depth one.

  121. 1024errnoThe error code the caller’s last failing syscall stored.System

    Takes no arguments.

    Returnsu64 — an Errno discriminant
    ErrorsCannot fail.

    Per thread, and cleared at the start of every handler that can fail. The value is the discriminant below, not a POSIX number.

Errno is a plain Rust enum, and what userspace reads is its discriminant. These are not the POSIX numbers; a program that hardcodes 2 for ENOENT is reading ENOMEM.

ValueNameMeaning
0ClearNo error. Every handler stores this before it does any work.
1EINVALInvalid argument passed to a syscall.
2ENOMEMMemory allocation failed or memory exhausted.
3EFAULTBad memory address provided by userspace.
4EBADFInvalid or closed file descriptor.
5EACCESOperation requires permissions the caller lacks.
6EPERMOperation not permitted for the current caller.
7ENOENTRequested file or directory does not exist.
8EEXISTAttempted to create an entry that already exists.
9ENOTDIRExpected a directory but encountered a non-directory entry.
10EISDIROperation required a regular file but encountered a directory.
11ENOSPCDevice or filesystem has no space left for the operation.
12EROFSWrite attempted on a read-only filesystem or device.
13EIOGeneric I/O failure from the filesystem or storage layer.
14EINTRSystem call interrupted, e.g. by a signal or a kill.
15ENOEXECFile format is not recognized as an executable.
16EAGAINResource temporarily unavailable; the operation would block.
17ENOTCONNSocket is not connected.
18ECONNREFUSEDConnection was refused by the remote host.
19EADDRINUSEAddress already in use.
20EPIPEBroken pipe: a write to a closed connection.
21EAFNOSUPPORTAddress family not supported.
22ESPIPESeek on a descriptor with no file offset: pipe, socket, tty.
23EBUSYDevice or resource in use, e.g. a disk backing a live mount.
24UNKNOWNPlaceholder for unmapped kernel error codes.

Filesystem failures reach userspace through a mapping rather than as their own codes: FileNotFound becomes ENOENT, NotAFile becomes EISDIR, NotADir becomes ENOTDIR, Busy becomes EBUSY, InvalidFs and InvalidArgument become EINVAL, and everything else, including a corrupt filesystem and an AHCI error, becomes EIO.

Four edits, in this order:

  1. A number constant and a dispatch arm in kernel/src/syscalls/mod.rs. The arm unpacks registers and calls the implementation; it does not contain logic.
  2. The implementation in the matching syscalls/*.rs, taking real types rather than registers, clearing the caller’s error code first and copying user memory through the checked helpers.
  3. A wrapper in programs/edos_lib/, or in the edos_rt crate and the std fork if it has to be reachable through std.
  4. A row here, since this page is transcribed from that table.