-
-
Notifications
You must be signed in to change notification settings - Fork 5
Syscall Reference
Complete reference for all 61 NyxOS system calls, numbered 0–60. One entry per call: synopsis, arguments, return values, errors and notes.
Numbers are defined in both kernel/core/kernel.h and user/syscall.h; wrappers are static inline in user/syscall.h; the dispatch is one switch in syscall_handler() (kernel/core/syscall.c).
For the calling convention and boundary hardening see Syscalls. To add one, see HOWTO-Add-a-system-call.
See also: Syscalls, Userspace, Kernel-Data-Structures, Security
| Notation | Meaning |
|---|---|
| Returns | Value in RAX
|
−1 |
Generic failure unless stated otherwise |
| validated | The kernel checks the pointer with user_ptr_ok/user_str_ok before use |
| cwd-relative | Resolved against the caller's working directory by copy_path_from_user
|
Important
Any buffer the kernel writes into must have every page already resident. The kernel cannot fault in a lazy-sbrk heap page on your behalf. Use a .bss array or memset the buffer first. This affects getdents, getprocs, getcwd, stat, fstat, time, gettimeofday and poll.
| # | Name | # | Name | # | Name |
|---|---|---|---|---|---|
| 0 | exit |
19 | mmap |
38 | accept |
| 1 | write |
20 | munmap |
39 | sendto |
| 2 | print |
21 | chdir |
40 | recvfrom |
| 3 | open |
22 | getcwd |
41 | sigprocmask |
| 4 | read |
23 | mkdir |
42 | alarm |
| 5 | close |
24 | unlink |
43 | poll |
| 6 | getpid |
25 | ttymode |
44 | stat |
| 7 | sbrk |
26 | mprotect |
45 | fstat |
| 8 | fsize |
27 | getprocs |
46 | lseek |
| 9 | exec |
28 | readkey |
47 | getppid |
| 10 | fork |
29 | dlopen |
48 | dup |
| 11 | waitpid |
30 | dlsym |
49 | rename |
| 12 | pipe |
31 | time |
50 | clone |
| 13 | execve |
32 | sleep |
51 | futex |
| 14 | dup2 |
33 | setfg |
52 | gettimeofday |
| 15 | getdents |
34 | socket |
53 | nanosleep |
| 16 | kill |
35 | connect |
54 | fbinfo |
| 17 | signal |
36 | bind |
55 | fbpresent |
| 18 | sigreturn |
37 | listen |
56 | getkeyevent |
Windows (v6.4.354): 57 win_create · 58 win_destroy · 59 win_present · 60 win_poll_event
void exit(int status);Terminate the calling process. Does not return.
| Argument | Meaning |
|---|---|
status |
Exit status, collected by the parent's waitpid
|
Behaviour. Marks the task PROC_ZOMBIE and yields forever. The scheduler skips non-PROC_RUN states, so the next tick switches away and never comes back. The address space and stacks are freed later by reap_zombies() from a safe context — a process cannot free the stack it is running on.
The kernel logs [USER] exit(n) on the serial console.
Important
A CLONE_VM thread must finish with exit(). It has nowhere to return to.
long getpid(void);Returns the calling process's pid. Cannot fail.
int getppid(void);Returns the parent's pid, or 0 if the process has no parent entry.
long fork(void);Create a copy-on-write clone of the calling process.
| Returns | In |
|---|---|
0 |
The child |
| child's pid | The parent |
−1 |
The parent, on failure |
Inherited. Address space (copy-on-write), open fds, cwd, environment, mmap VMAs (file buffers deep-copied), signal dispositions, program_break.
Not inherited. tty_raw — only the process that asked for raw mode sees it.
Mechanics. clone_page_directory_cow() walks the user half: writable leaves are downgraded to read-only + PTE_COW in both parent and child with the frame refcount bumped; read-only pages (program text) are shared as-is. The first write by either side faults, and vm_handle_fault allocates a private copy. See Memory-Management.
long execve(const char* path, char* const argv[], char* const envp[]);Replace the calling process's image in place.
| Argument | Meaning |
|---|---|
path |
validated, cwd-relative. The ELF to load |
argv |
NULL-terminated array, or 0 to omit |
envp |
NULL-terminated array, or 0 to omit |
Returns. Does not return on success. −1 on failure.
Preserved. pid, ppid, open fds, cwd.
Replaced. Address space, mmap VMAs (dropped), heap.
Reset. tty_raw returns to canonical — a crashed child cannot leave the shell without echo.
Entry stack. Built in SysV layout, read by crt0:
[rsp] argc
[rsp+8] argv[0]
… argv[argc-1]
NULL
envp[0] … NULL
| Limit | Value |
|---|---|
| Maximum arguments | 8 |
| Maximum length per argument | 63 characters |
long exec(const char* path);Spawn path and wait for it. Legacy — prefer fork + execve + waitpid.
| Argument | Meaning |
|---|---|
path |
validated, up to 128 bytes |
Returns. The child's exit code, or −1 if the file cannot be opened or is not a valid ELF.
long waitpid(int pid, int* status);
long waitpid3(int pid, int* status, int options);Wait for a child to change state and collect its status.
| Argument | Meaning |
|---|---|
pid |
Child to wait for. <= 0 waits for any child |
status |
validated, receives the exit status. May be 0
|
options |
Bitmask, see below |
| Option | Value | Effect |
|---|---|---|
WNOHANG |
1 | Do not block; return 0 if the child is still running |
WUNTRACED |
2 | Also report a child that stopped (Ctrl-Z) rather than exited |
| Returns | Meaning |
|---|---|
| child's pid | The child exited or stopped; *status is filled |
0 |
WNOHANG and the child is still running |
−1 |
No such child |
Decoding a status.
| Macro | Meaning |
|---|---|
WIFSTOPPED(s) |
True if the child stopped rather than exited (bit WSTOPPED = 0x10000) |
WSTOPSIG(s) |
The stopping signal, s & 0xFF
|
A process killed by an uncaught signal exits with status 128 + signo — 139 for SIGSEGV, 143 for SIGTERM.
Blocking. The caller is parked PROC_BLOCKED with waiting_for set. This is a real block, made possible by each process having its own kernel stack.
int clone(void* fn, void* stack_top, void* arg, unsigned long flags);Create a thread sharing the caller's address space.
| Argument | Meaning |
|---|---|
fn |
Entry function, called as fn(arg)
|
stack_top |
The high end of a block you own; the stack grows down. 16-byte aligned |
arg |
Passed to fn
|
flags |
Must include CLONE_VM (0x100) |
Returns. The new tid, or −1.
Shared with the thread group. Address space, heap (sbrk), mmap VMA table, file-descriptor table. All resolved through the group leader named by tgid.
Warning
Without CLONE_VM the call fails. Use fork() for a separate address space. The thread must finish with exit(). Thread groups stay pinned to one CPU, because they share page tables.
int futex_wait(volatile int* uaddr, int val);
int futex_wake(volatile int* uaddr, int n);| Operation | Value | Behaviour |
|---|---|---|
FUTEX_WAIT |
0 | Sleep while *uaddr == val. Returns immediately if the value already differs |
FUTEX_WAKE |
1 | Wake up to n waiters; returns how many were woken |
The compare-and-sleep is what makes a lock race-free — a value change between your test and the sleep cannot be lost. The kernel records the physical address in futex_key, so it works across a shared mapping.
long setfg(long pid);Make pid the terminal foreground process, so keyboard signals target it instead of the shell.
| Argument | Meaning |
|---|---|
pid |
Process to foreground. 0 clears |
Returns. 0, or −1 for an unknown pid.
Ctrl-C then delivers SIGINT and Ctrl-Z delivers SIGTSTP to that process. The shell points this at a job while it runs in the foreground and back at itself afterwards. See Process-Management.
long kill(int pid, int sig);
long raise(int sig); /* kill(getpid(), sig) */Post a signal to a process. Delivered at that process's next return to ring 3.
| Argument | Meaning |
|---|---|
pid |
Target |
sig |
Signal number. 0 probes existence without sending |
Returns. 0, or −1 if there is no such process.
Signal numbers.
| # | Name | Default action | Catchable |
|---|---|---|---|
| 1 | SIGHUP |
Terminate | Yes |
| 2 | SIGINT |
Terminate | Yes — Ctrl-C |
| 3 | SIGQUIT |
Terminate | Yes |
| 4 | SIGILL |
Terminate | Yes — raised by a CPU fault |
| 6 | SIGABRT |
Terminate | Yes |
| 8 | SIGFPE |
Terminate | Yes — raised by a CPU fault |
| 9 | SIGKILL |
Terminate | No |
| 10 | SIGUSR1 |
Terminate | Yes |
| 11 | SIGSEGV |
Terminate | Yes — raised by a CPU fault |
| 12 | SIGUSR2 |
Terminate | Yes |
| 13 | SIGPIPE |
Terminate | Yes |
| 14 | SIGALRM |
Terminate | Yes |
| 15 | SIGTERM |
Terminate | Yes |
| 17 | SIGCHLD |
Ignore | Yes |
| 18 | SIGCONT |
Continue | Yes |
| 19 | SIGSTOP |
Stop | No |
| 20 | SIGTSTP |
Stop | Yes — Ctrl-Z |
NSIG is 32, because the pending and mask sets are uint32_t bitmaps.
sighandler_t signal(int sig, sighandler_t handler);Set the disposition of a signal.
handler |
Effect |
|---|---|
SIG_DFL (0) |
Default — terminate with status 128 + signo
|
SIG_IGN (1) |
Drop silently |
| function pointer | Enter the handler with the signal number in RDI
|
Returns. The previous disposition, or SIG_ERR ((sighandler_t)-1) for an invalid or uncatchable signal.
The wrapper passes the libc __sigreturn trampoline as a third argument, so the handler can return normally.
Delivery. The interrupted ring-3 frame is saved into sig_saved[18], the trampoline address is pushed onto the user stack, and RIP is rewritten to the handler. Returning runs SYS_SIGRETURN.
CPU faults become signals. A ring-3 page fault, divide error or illegal instruction is delivered as SIGSEGV, SIGFPE or SIGILL. With a handler installed the program recovers; without one it dies and the kernel carries on.
void sigreturn(void);Restore the context saved when a handler was entered. Not called directly — it is the return address crt0's __sigreturn trampoline jumps to.
long sigprocmask(int how, unsigned long set, unsigned long* oldset);Read or change the blocked-signal mask (a 32-bit set, bit 1 << signo).
how |
Value | Effect |
|---|---|---|
SIG_BLOCK |
0 | Add set to the mask |
SIG_UNBLOCK |
1 | Remove set from the mask |
SIG_SETMASK |
2 | Replace the mask with set
|
oldset (validated, may be NULL) receives the previous mask. This is the primitive behind sigsetjmp/siglongjmp.
unsigned int alarm(unsigned int seconds);Schedule SIGALRM after seconds. 0 cancels a pending alarm.
Returns. Seconds remaining on any previous alarm, or 0.
The deadline is stored in alarm_tick; irq_scheduler_tick posts the signal once tick_count passes it. Without a handler the default action terminates the process.
long open(const char* path, int flags, int mode);| Argument | Meaning |
|---|---|
path |
validated, cwd-relative |
flags |
See below |
mode |
Accepted; permission bits are stored but not enforced |
| Flag | Value | Effect |
|---|---|---|
O_RDONLY |
0 | Default |
O_CREAT |
1 | Create if absent |
O_TRUNC |
2 | Empty an existing file — the shell's >
|
O_APPEND |
4 | Seek to EOF before writing — the shell's >>
|
Returns. A file descriptor (UFD_BASE + slot), or −1.
Descriptors are opaque small integers indexed into a per-process table of PROC_MAX_FDS (32) entries. The internal VFS handle is never exposed. A thread group shares one table.
long read(int fd, void* buf, long count);
long recv(int fd, void* buf, long len, int flags); /* alias, flags ignored */| Returns | Meaning |
|---|---|
> 0 |
Bytes read |
0 |
EOF — end of file, or all pipe writers closed |
< 0 |
Error, or interrupted by a signal (-EINTR) |
Sources. Regular files, EXT2 mount files, /proc generated nodes, /dev specials, pipes, sockets, and fd 0 (the keyboard).
fd 0 behaviour depends on the discipline set by ttymode:
| Mode | Behaviour |
|---|---|
TTY_CANON |
Blocking line read with echo and backspace editing |
TTY_RAW |
Byte at a time, no echo, arrows delivered as ANSI escape sequences |
A blocking read is interrupted by a signal and returns negative — Ctrl-C at a prompt does not kill the shell.
long write(int fd, const void* buf, long len);
long send(int fd, const void* buf, long len, int flags); /* alias, flags ignored */Returns. Bytes written, or −1.
| fd | Destination |
|---|---|
| 1, 2 | Terminal (and the serial console) |
| ≥ 3 | The file, pipe or socket the fd names |
Writes to /dev/null and /dev/zero are accepted and discarded. File writes advance the per-fd offset, so successive writes append rather than overwrite.
long close(int fd);Returns. 0, or −1 for a bad fd.
Closing a mount-backed file flushes it to disk — this is what makes writes to /mnt persist. Closing the last reference to a pipe end signals EOF to the other side. Any fd left open at process exit is force-closed by close_proc_fds(), which logs [reap] force-closed leaked fd(s).
long fsize(int fd);Returns. The file's size in bytes, or −1.
int stat(const char* path, struct stat* st);| Argument | Meaning |
|---|---|
path |
validated, cwd-relative |
st |
validated, 12 bytes |
Returns. 0, or −1 if the path does not exist.
struct stat {
unsigned int st_size; /* bytes; 0 for directories */
unsigned int st_mode; /* S_IFDIR|0755 or S_IFREG|0644 */
unsigned int st_ino; /* reserved, always 0 */
};| Macro | Value | Test |
|---|---|---|
S_IFMT |
0xF000 |
Type mask |
S_IFDIR |
0x4000 |
S_ISDIR(m) |
S_IFREG |
0x8000 |
S_ISREG(m) |
int fstat(int fd, struct stat* st);As stat, on an open fd. A pipe or socket reports size 0 and a regular-file mode.
long lseek(int fd, long offset, int whence);whence |
Value | New offset |
|---|---|---|
SEEK_SET |
0 | offset |
SEEK_CUR |
1 | current + offset
|
SEEK_END |
2 | size + offset
|
Returns. The new absolute offset, or −1.
Returns −1 for a pipe or socket (not seekable), or if the computed offset is negative.
long getdents(const char* path, nyx_dirent_t* buf, int max);| Argument | Meaning |
|---|---|
path |
validated, cwd-relative directory |
buf |
validated, receives up to max records |
max |
Capacity in records |
Returns. Number of entries written, or −1.
typedef struct {
char name[64];
unsigned int type; /* 1 = directory, otherwise a regular file */
} nyx_dirent_t; /* exactly 68 bytes, no padding */Works over the ramdisk, EXT2 mounts and /proc. This is the primitive behind ls and the shell's path completion.
Warning
The kernel writes into buf. Use a .bss array or memset it first, or you will get partial results with no error returned.
long mkdir(const char* path, int mode);validated, cwd-relative. The parent must exist. Returns 0 or −1.
long unlink(const char* path);Remove a file, or an empty directory. validated, cwd-relative. Returns 0 or −1.
int rename(const char* oldpath, const char* newpath);Move or rename an entry. Both paths are validated and cwd-relative. Returns 0, or −1 if the source is missing or the move did not land.
long chdir(const char* path);Set the calling process's working directory. Returns 0, or −1 if the path is not a directory.
The cwd is stored absolute and normalised (. and .. resolved) in cwd[MAX_PATH], inherited across fork and kept across execve.
long getcwd(char* buf, long size);Returns. The length copied, or −1.
long pipe(int fds[2]);Create an anonymous pipe. fds[0] is the read end, fds[1] the write end.
Returns. 0, or −1.
| Property | Behaviour |
|---|---|
| Read | Blocks until a writer writes |
| EOF |
read returns 0 once all writers have closed |
| Write | Non-blocking |
| Ends | Reference-counted, so they survive fork and dup2
|
A pipe fd carries UFD_PIPE_FLAG in its internal handle.
long dup2(int oldfd, int newfd);Duplicate oldfd onto newfd, closing newfd first if it is open.
Returns. newfd, or −1.
The redirection primitive: dup2(pipefd[1], 1) makes a process's stdout flow into a pipe. Works for pipe ends (reference-counted) and VFS handles (moved), which is what implements >, >> and <.
int dup(int oldfd);Returns. The lowest available fd referring to the same stream, or −1. Both fds stay open.
Note
A VFS fd is a node pointer, so dup increments the node's open_refs. A version that did not do this made dup of a mount-backed file a double free.
long sbrk(long increment);Move the program break.
Returns. The previous break, or −1.
The break moves without allocating anything. Pages materialise on first write, faulted in by vm_handle_fault inside the window [heap_start, program_break). A malloc(8000) therefore costs only the pages actually touched. Inherited across fork; shared across a thread group.
void* mmap(void* addr, unsigned long length, int prot,
int flags, int fd, long offset);| Argument | Meaning |
|---|---|
addr |
Hint; the kernel chooses the base |
length |
Bytes, rounded up to pages |
prot |
PROT_NONE 0, PROT_READ 1, PROT_WRITE 2, PROT_EXEC 4 |
flags |
MAP_PRIVATE 0x02, MAP_ANONYMOUS 0x20
|
fd |
File to map, or ignored with MAP_ANONYMOUS
|
offset |
Starting offset within the file |
Returns. The base address, or MAP_FAILED ((void*)-1).
| Kind | Behaviour |
|---|---|
| Anonymous | Demand-zero pages, faulted in on first touch with prot honoured — writable only with PROT_WRITE, NX unless PROT_EXEC
|
| File-backed | The file is snapshotted into a per-VMA kernel buffer from offset; faulting pages copy their slice out of it |
Mappings live at MMAP_BASE (0x100000000) upward — clear of both the heap and the stack. A process has PROC_MAX_VMAS (16) VMA slots. Inherited copy-on-write across fork (file buffers deep-copied); dropped by execve.
offset only became real in v5.8.20, when the entry path started marshalling a sixth argument.
long munmap(void* addr, unsigned long length);Returns. 0, or −1.
Frees present pages (refcount-aware) and drops the VMAs; file buffers are freed with the VMA. A partial range splits the VMA rather than silently doing nothing. Issues a TLB shootdown IPI so no other core keeps a stale translation.
long mprotect(void* addr, unsigned long len, int prot);Returns. 0, or −1.
Rewrites the flags of present pages and the VMA's recorded prot, so pages faulted in later get the new protection too. A partial range splits the VMA. Issues a TLB shootdown.
long ttymode(int mode);| Mode | Value | stdin behaviour |
|---|---|---|
TTY_CANON |
0 | Kernel line discipline: echoed, backspace-edited lines |
TTY_RAW |
1 | Byte at a time, no echo, arrows as ESC [ A/B/C/D
|
Returns. The previous mode.
Not inherited on fork; reset by execve, so a crashed child cannot leave the terminal without echo. Restore it yourself on the normal exit path anyway.
long readkey(long timeout_ms);Block for a single keypress.
timeout_ms |
Behaviour |
|---|---|
0 |
Block forever — for editors |
> 0 |
Block up to that many milliseconds — for TUI refresh loops |
| Returns | Meaning |
|---|---|
> 0 |
The key: an ASCII byte, or an extended keycode >= 0x80 for arrows and navigation |
0 |
Timeout elapsed with no key |
< 0 |
Interrupted by a signal |
No echo, and independent of ttymode. top uses a positive timeout (redraw when nothing was pressed); edit blocks.
int getkeyevent(int* pressed, int* code);Non-blocking raw key event — the fullscreen-game path (DOOM's DG_GetKey).
Returns. 1 and fills both outputs if an event was waiting, 0 if the ring is empty.
| Output | Meaning |
|---|---|
*pressed |
1 = key down, 0 = key up |
*code |
A layout-independent Set-1 scancode; bit 7 flags an E0-extended navigation key |
Poll it each frame. Every key arrives as both a press and a release.
int fbinfo(unsigned int out3[3]);Fills out3 with {width, height, bpp}. validated. Returns 0 or negative.
int fbpresent(const void* buf, unsigned int w, unsigned int h);Blit a w × h 32-bpp buffer to the screen, nearest-neighbour scaled to fullscreen. Pixel format is 0x00RRGGBB — BGRX in memory.
Call once per frame. While a program keeps calling this it owns the whole screen and the desktop compositor yields; the desktop returns shortly after the program stops or exits.
A ring-3 program can open a real desktop window without a fullscreen takeover; the compositor keeps running around it. wintest is the example, and the N-language nwin draws one from N (see N-Language).
int win_create(unsigned int w, unsigned int h, const char* title);Open a window with a w × h client area and the given title. validated. Returns a window id, or −1.
int win_destroy(int id);Close the window. Idempotent — returns 0 even if the window was already gone.
int win_present(int id, const void* buf, unsigned int w, unsigned int h);Blit a w × h XRGB (0x00RRGGBB) buffer as the whole client area. Returns 0, or −1 on a bad id/size.
int win_poll_event(int id, win_event_t* ev);Pop one input event into *ev (non-blocking). Returns 1 if an event was returned, 0 if the queue was empty, −1 on a bad id.
Full protocol detail in Networking-Stack. There are MAX_SOCKETS (32) slots and TCP_MAX_CONNS (32) connections. A socket fd carries UFD_SOCK_FLAG and works with read, write, close and poll.
long socket(int domain, int type, int protocol);| Argument | Accepted |
|---|---|
domain |
AF_INET (2) |
type |
SOCK_STREAM (1) for TCP, SOCK_DGRAM (2) for UDP |
protocol |
0 |
Returns. A file descriptor, or −1.
long connect(int fd, unsigned int ip, int port);| Argument | Meaning |
|---|---|
ip |
Network order — build with inet_ipv4(a,b,c,d)
|
port |
Host order |
Returns. 0 on success, −1 on failure. Blocks until the TCP three-way handshake completes.
static inline unsigned int inet_ipv4(int a, int b, int c, int d);
/* first octet in the low byte, matching the kernel convention */long bind(int fd, unsigned int ip, int port);Record the local port. INADDR_ANY (0) binds all interfaces. Returns 0 or −1.
long listen(int fd, int backlog);Open the bound port passively. Returns 0 or −1.
long accept(int fd);Blocks until a client connects. Returns a new fd for that connection, or −1. The listener fd stays open for further clients.
long sendto(int fd, const void* buf, long len, int flags,
unsigned int ip, int port);Send a UDP datagram. flags is accepted and ignored. The socket auto-binds an ephemeral source port on the first send if it was not bind'd.
Returns. Bytes sent, or −1.
long recvfrom(int fd, void* buf, long len, int flags,
unsigned int* ip, int* port);Blocks for a datagram. *ip (network order) and *port (host order) receive the sender's address; either may be NULL.
Returns. The datagram length, truncated to len, or −1.
long poll(struct pollfd* fds, int nfds, int timeout);Wait for events on a set of descriptors.
struct pollfd { int fd; short events; short revents; };| Flag | Value | Meaning |
|---|---|---|
POLLIN |
0x001 |
Readable |
POLLOUT |
0x004 |
Writable |
POLLERR |
0x008 |
Error |
POLLHUP |
0x010 |
Hangup |
POLLNVAL |
0x020 |
Bad fd — set by the kernel |
timeout |
Behaviour |
|---|---|
0 |
Return immediately |
> 0 |
Milliseconds |
< 0 |
Block forever |
| Returns | Meaning |
|---|---|
> 0 |
Number of fds with a non-zero revents
|
0 |
Timeout |
−1 |
Error |
Works over sockets, pipes and stdin — this is what makes nc full-duplex.
long time(nyx_tm* t);Fill t with broken-down local time from the RTC. validated. Returns 0 or −1.
typedef struct {
int sec; /* 0–59 */
int min; /* 0–59 */
int hour; /* 0–23 */
int mday; /* 1–31 */
int mon; /* 1–12 */
int year; /* full four-digit year */
} nyx_tm;int gettimeofday(struct timeval* tv, void* tz);Wall-clock time since the Unix epoch. Seconds come from the RTC treated as UTC; microseconds from the 1000 Hz tick. tz is obsolete and ignored.
struct timeval { long tv_sec; long tv_usec; };tv_sec is 64-bit, so this is y2038-safe. Returns 0, or −1 on a bad pointer.
The conversion uses a civil-days algorithm valid for any Gregorian date.
long sleep_ms(long ms);
long sleep_sec(long s); /* sleep_ms(s * 1000) */Block for ms milliseconds. Other processes run meanwhile.
Returns. 0, or negative if a signal interrupted it.
The task is parked PROC_BLOCKED with wake_tick set; the scheduler's per-tick wait-queue pass wakes it.
int nanosleep(const struct timespec* req, struct timespec* rem);
int usleep(long usec);struct timespec { long tv_sec; long tv_nsec; };Sleeps tv_sec + tv_nsec, rounded up to the 1 ms timer tick — its finest resolution. rem (may be NULL) is zeroed; no precise remainder is tracked.
Returns. 0, or negative (-EINTR) if a signal cut it short.
long getprocs(nyx_procinfo_t* buf, int max);Snapshot the process table. The process analogue of getdents, and the primitive behind ps.
Returns. Number of live processes written, or −1.
typedef struct {
unsigned int pid;
unsigned int ppid;
unsigned int state; /* PROC_* — 0 parked, 1 run, 2 zombie, 3 blocked, 4 stopped */
unsigned int cpu_time; /* accumulated ticks */
char comm[32];
} nyx_procinfo_t; /* exactly 48 bytes, no padding */Warning
As with getdents, every page of buf must be resident before the call.
long dlopen(const char* path);Load a prelinked shared object and map it into the process on demand.
Returns. A handle >= 1, or −1.
void* dlsym(long handle, const char* name);Resolve a symbol to its address. Cast it to the right function or data pointer.
Returns. The address, or NULL.
Libraries load at fixed addresses, so there is no relocation to perform. SHARED_LIBC_BASE is 0x30000000.
void print(const char* s);Debug print of a NUL-terminated string to the kernel console. Legacy — use write(1, …). The string is copied in with a bounded copy_str_from_user.
NyxOS does not have a full errno. Most calls return −1 for any failure. The exceptions:
| Call | Distinct value | Meaning |
|---|---|---|
read |
0 |
EOF |
read, sleep, nanosleep, readkey
|
negative | Interrupted by a signal (-EINTR) |
waitpid |
0 |
WNOHANG, child still running |
waitpid |
−1 |
No such child |
poll |
0 |
Timeout |
mmap |
MAP_FAILED |
Not −1 as a plain integer |
signal |
SIG_ERR |
Invalid or uncatchable signal |
fork |
0 / pid |
Not an error — which side you are on |
| Range | Status |
|---|---|
| 0–56 | Allocated |
| 57–255 | Free. SYS_TABLE_SIZE is 256 |
- Syscalls — the calling convention, register map and boundary hardening
- HOWTO-Add-a-system-call — the procedure for adding number 57
-
Kernel-Data-Structures —
process_tand the fd table these operate on - Userspace — the libc built on top of these
- Security — what the boundary defends against
- System V AMD64 ABI — the calling convention
- POSIX.1-2017 System Interfaces — The Open Group, for the semantics these approximate
- Intel SDM Vol. 2 — SYSCALL/SYSRET — Intel
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