//! Typed system_call surface for user space — thin wrappers over the raw `system_call` //! stubs, one per kernel call. Numbers come from `abi.SystemCall`, the single //! source of truth shared with the kernel dispatcher. const abi = @import("abi"); const sc = @import("system-call.zig"); /// `mmap` protection flags (matching the usual C bit values). Grants are always /// readable+writable today; the kernel does not yet honour finer prot. pub const PROT_READ: usize = abi.prot_read; pub const PROT_WRITE: usize = abi.prot_write; pub const PROT_EXEC: usize = abi.prot_exec; /// Give up the rest of this quantum. pub fn yield() void { _ = sc.systemCall0(.yield); } /// Write raw bytes to the kernel log (a bring-up diagnostic; real output goes /// through the console/VFS later). Returns the byte count, or a wrapped -1. pub fn write(message: []const u8) usize { return sc.systemCall2(.debug_write, @intFromPtr(message.ptr), message.len); } /// Block the caller for `ms` milliseconds. pub fn sleep(ms: usize) void { _ = sc.systemCall1(.sleep, ms); } /// Monotonic nanoseconds since boot — a time source for timeouts and short delays. It /// only ever moves forward. This is *not* wall-clock time (no date, no timezone — that /// is a user-space service layered on top). Deadline pattern for a bounded poll loop: /// /// const deadline = clock() + timeout_ns; /// while (clock() < deadline) { ... } pub fn clock() u64 { return @intCast(sc.systemCall0(.clock)); } /// End the process. Never returns. pub fn exit(code: usize) noreturn { _ = sc.systemCall1(.exit, code); unreachable; // the kernel never returns from exit } /// Start the binary bundled in the initial-ramdisk under `name` as a new ring-3 /// process, returning true on success. This is how a supervisor (the device manager) /// launches a driver it matched — danos-native, not POSIX (a spawn/exec family comes /// with the process work later). pub fn spawn(name: []const u8) bool { return sc.systemCall2(.system_spawn, @intFromPtr(name.ptr), name.len) == 0; } /// Grant `len` bytes (rounded up to whole pages) of fresh, zeroed, writable /// memory and return the base virtual address. On failure returns a value in the /// top page (see `mmapFailed`). The user heap grows through this call. pub fn mmap(len: usize, prot: usize) usize { return sc.systemCall2(.mmap, len, prot); } /// Release a range previously handed out by `mmap`. pub fn munmap(base: usize, len: usize) usize { return sc.systemCall2(.munmap, base, len); } /// Whether an `mmap` return value is an error (the kernel returns a wrapped /// -errno, which lands in the top page — no real grant base is ever that high). pub inline fn mmapFailed(ret: usize) bool { return ret > ~@as(usize, 0) - 4095; }