|
const std = @import("../std.zig"); const builtin = @import("builtin"); |
fd_tGets whatever the last errstr was |
pub const fd_t = i32; |
STDIN_FILENOPer process profiling |
pub const STDIN_FILENO = 0; |
STDOUT_FILENOknown to be 0(ptr) |
pub const STDOUT_FILENO = 1; |
STDERR_FILENOknown to be 4(ptr) |
pub const STDERR_FILENO = 2; |
PATH_MAXcycle clock frequency if there is one, 0 otherwise |
pub const PATH_MAX = 1023; |
syscall_bitscycles spent in kernel |
pub const syscall_bits = switch (builtin.cpu.arch) { .x86_64 => @import("plan9/x86_64.zig"), else => @compileError("more plan9 syscall implementations (needs more inline asm in stage2"), }; /// Ported from /sys/include/ape/errno.h |
Ecycles spent in process (kernel + user) |
pub const E = enum(u16) { SUCCESS = 0, DOM = 1000, RANGE = 1001, PLAN9 = 1002, |
init()might as well put the pid here |
@"2BIG" = 1, ACCES = 2, AGAIN = 3, // WOULDBLOCK = 3, // TODO errno.h has 2 names for 3 BADF = 4, BUSY = 5, CHILD = 6, DEADLK = 7, EXIST = 8, FAULT = 9, FBIG = 10, INTR = 11, INVAL = 12, IO = 13, ISDIR = 14, MFILE = 15, MLINK = 16, NAMETOOLONG = 17, NFILE = 18, NODEV = 19, NOENT = 20, NOEXEC = 21, NOLCK = 22, NOMEM = 23, NOSPC = 24, NOSYS = 25, NOTDIR = 26, NOTEMPTY = 27, NOTTY = 28, NXIO = 29, PERM = 30, PIPE = 31, ROFS = 32, SPIPE = 33, SRCH = 34, XDEV = 35, |
ERRMAXhangup |
// bsd networking software NOTSOCK = 36, PROTONOSUPPORT = 37, // PROTOTYPE = 37, // TODO errno.h has two names for 37 CONNREFUSED = 38, AFNOSUPPORT = 39, NOBUFS = 40, OPNOTSUPP = 41, ADDRINUSE = 42, DESTADDRREQ = 43, MSGSIZE = 44, NOPROTOOPT = 45, SOCKTNOSUPPORT = 46, PFNOSUPPORT = 47, ADDRNOTAVAIL = 48, NETDOWN = 49, NETUNREACH = 50, NETRESET = 51, CONNABORTED = 52, ISCONN = 53, NOTCONN = 54, SHUTDOWN = 55, TOOMANYREFS = 56, TIMEDOUT = 57, HOSTDOWN = 58, HOSTUNREACH = 59, GREG = 60, |
errstr()interrupt |
// These added in 1003.1b-1993 CANCELED = 61, INPROGRESS = 62, |
Plinkquit |
// We just add these to be compatible with std.os, which uses them, // They should never get used. DQUOT, CONNRESET, OVERFLOW, LOOP, TXTBSY, |
Tosillegal instruction (not reset when caught) |
pub fn init(r: usize) E { const signed_r: isize = @bitCast(r); const int = if (signed_r > -4096 and signed_r < 0) -signed_r else 0; return @enumFromInt(int); } }; // The max bytes that can be in the errstr buff pub const ERRMAX = 128; var errstr_buf: [ERRMAX]u8 = undefined; /// Gets whatever the last errstr was pub fn errstr() []const u8 { _ = syscall_bits.syscall2(.ERRSTR, @intFromPtr(&errstr_buf), ERRMAX); return std.mem.span(@as([*:0]u8, @ptrCast(&errstr_buf))); } pub const Plink = anyopaque; pub const Tos = extern struct { /// Per process profiling prof: extern struct { /// known to be 0(ptr) pp: *Plink, /// known to be 4(ptr) next: *Plink, last: *Plink, first: *Plink, pid: u32, what: u32, }, /// cycle clock frequency if there is one, 0 otherwise cyclefreq: u64, /// cycles spent in kernel kcycles: i64, /// cycles spent in process (kernel + user) pcycles: i64, /// might as well put the pid here pid: u32, clock: u32, // top of stack is here }; |
getpid()used by abort |
pub var tos: *Tos = undefined; // set in start.zig pub fn getpid() u32 { return tos.pid; } |
SIGfloating point exception |
pub const SIG = struct { /// hangup |
HUPkill (cannot be caught or ignored) |
pub const HUP = 1; /// interrupt |
INTsegmentation violation |
pub const INT = 2; /// quit |
QUITwrite on a pipe with no one to read it |
pub const QUIT = 3; /// illegal instruction (not reset when caught) |
ILLalarm clock |
pub const ILL = 4; /// used by abort |
ABRTsoftware termination signal from kill |
pub const ABRT = 5; /// floating point exception |
FPEuser defined signal 1 |
pub const FPE = 6; /// kill (cannot be caught or ignored) |
KILLuser defined signal 2 |
pub const KILL = 7; /// segmentation violation |
SEGVbus error |
pub const SEGV = 8; /// write on a pipe with no one to read it |
PIPEchild process terminated or stopped |
pub const PIPE = 9; /// alarm clock |
ALRMcontinue if stopped |
pub const ALRM = 10; /// software termination signal from kill |
TERMstop |
pub const TERM = 11; /// user defined signal 1 |
USR1interactive stop |
pub const USR1 = 12; /// user defined signal 2 |
USR2read from ctl tty by member of background |
pub const USR2 = 13; /// bus error |
BUSwrite to ctl tty by member of background |
pub const BUS = 14; // The following symbols must be defined, but the signals needn't be supported /// child process terminated or stopped |
CHLDBrk sets the system's idea of the lowest bss location not used by the program (called the break) to addr rounded up to the next multiple of 8 bytes. Locations not less than addr and below the stack pointer may cause a memory violation if accessed. -9front brk(2) |
pub const CHLD = 15; /// continue if stopped |
CONT |
pub const CONT = 16; /// stop |
STOP |
pub const STOP = 17; /// interactive stop |
TSTP |
pub const TSTP = 18; /// read from ctl tty by member of background |
TTIN |
pub const TTIN = 19; /// write to ctl tty by member of background |
TTOU |
pub const TTOU = 20; }; |
sigset_t |
pub const sigset_t = c_long; |
empty_sigset |
pub const empty_sigset = 0; |
siginfo_t |
pub const siginfo_t = c_long; // TODO plan9 doesn't have sigaction_fn. Sigaction is not a union, but we include it here to be compatible. |
Sigaction |
pub const Sigaction = extern struct { |
handler_fn |
pub const handler_fn = *const fn (i32) callconv(.c) void; |
sigaction_fn |
pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.c) void; |
AT |
handler: extern union { handler: ?handler_fn, sigaction: ?sigaction_fn, }, mask: sigset_t, flags: c_int, }; pub const AT = struct { |
FDCWD |
pub const FDCWD = -100; // we just make up a constant; FDCWD and openat don't actually exist in plan9 }; // TODO implement sigaction // right now it is just a shim to allow using start.zig code |
sigaction() |
pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigaction) usize { _ = oact; _ = act; _ = sig; return 0; } |
SYS |
pub const SYS = enum(usize) { SYSR1 = 0, _ERRSTR = 1, BIND = 2, CHDIR = 3, CLOSE = 4, DUP = 5, ALARM = 6, EXEC = 7, EXITS = 8, _FSESSION = 9, FAUTH = 10, _FSTAT = 11, SEGBRK = 12, _MOUNT = 13, OPEN = 14, _READ = 15, OSEEK = 16, SLEEP = 17, _STAT = 18, RFORK = 19, _WRITE = 20, PIPE = 21, CREATE = 22, FD2PATH = 23, BRK_ = 24, REMOVE = 25, _WSTAT = 26, _FWSTAT = 27, NOTIFY = 28, NOTED = 29, SEGATTACH = 30, SEGDETACH = 31, SEGFREE = 32, SEGFLUSH = 33, RENDEZVOUS = 34, UNMOUNT = 35, _WAIT = 36, SEMACQUIRE = 37, SEMRELEASE = 38, SEEK = 39, FVERSION = 40, ERRSTR = 41, STAT = 42, FSTAT = 43, WSTAT = 44, FWSTAT = 45, MOUNT = 46, AWAIT = 47, PREAD = 50, PWRITE = 51, TSEMACQUIRE = 52, _NSEC = 53, }; |
write() |
pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { return syscall_bits.syscall4(.PWRITE, @bitCast(@as(isize, fd)), @intFromPtr(buf), count, @bitCast(@as(isize, -1))); } |
pwrite() |
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: isize) usize { return syscall_bits.syscall4(.PWRITE, @bitCast(@as(isize, fd)), @intFromPtr(buf), count, @bitCast(offset)); } |
read() |
pub fn read(fd: i32, buf: [*]const u8, count: usize) usize { return syscall_bits.syscall4(.PREAD, @bitCast(@as(isize, fd)), @intFromPtr(buf), count, @bitCast(@as(isize, -1))); } |
pread() |
pub fn pread(fd: i32, buf: [*]const u8, count: usize, offset: isize) usize { return syscall_bits.syscall4(.PREAD, @bitCast(@as(isize, fd)), @intFromPtr(buf), count, @bitCast(offset)); } |
open() |
pub fn open(path: [*:0]const u8, flags: u32) usize { return syscall_bits.syscall2(.OPEN, @intFromPtr(path), @bitCast(@as(isize, flags))); } |
openat() |
pub fn openat(dirfd: i32, path: [*:0]const u8, flags: u32, _: mode_t) usize { // we skip perms because only create supports perms if (dirfd == AT.FDCWD) { // openat(AT_FDCWD, ...) == open(...) return open(path, flags); } var dir_path_buf: [std.fs.max_path_bytes]u8 = undefined; var total_path_buf: [std.fs.max_path_bytes + 1]u8 = undefined; const rc = fd2path(dirfd, &dir_path_buf, std.fs.max_path_bytes); if (rc != 0) return rc; var fba = std.heap.FixedBufferAllocator.init(&total_path_buf); var alloc = fba.allocator(); const dir_path = std.mem.span(@as([*:0]u8, @ptrCast(&dir_path_buf))); const total_path = std.fs.path.join(alloc, &.{ dir_path, std.mem.span(path) }) catch unreachable; // the allocation shouldn't fail because it should not exceed max_path_bytes fba.reset(); const total_path_z = alloc.dupeZ(u8, total_path) catch unreachable; // should not exceed max_path_bytes + 1 return open(total_path_z.ptr, flags); } |
fd2path() |
pub fn fd2path(fd: i32, buf: [*]u8, nbuf: usize) usize { return syscall_bits.syscall3(.FD2PATH, @bitCast(@as(isize, fd)), @intFromPtr(buf), nbuf); } |
create() |
pub fn create(path: [*:0]const u8, omode: mode_t, perms: usize) usize { return syscall_bits.syscall3(.CREATE, @intFromPtr(path), @bitCast(@as(isize, omode)), perms); } |
exit() |
pub fn exit(status: u8) noreturn { if (status == 0) { exits(null); } else { // TODO plan9 does not have exit codes. You either exit with 0 or a string const arr: [1:0]u8 = .{status}; exits(&arr); } } |
exits() |
pub fn exits(status: ?[*:0]const u8) noreturn { _ = syscall_bits.syscall1(.EXITS, if (status) |s| @intFromPtr(s) else 0); unreachable; } |
close() |
pub fn close(fd: i32) usize { return syscall_bits.syscall1(.CLOSE, @bitCast(@as(isize, fd))); } |
mode_t |
pub const mode_t = i32; |
AccessMode |
pub const AccessMode = enum(u2) { RDONLY, WRONLY, RDWR, EXEC, }; |
O |
pub const O = packed struct(u32) { access: AccessMode, _2: u2 = 0, TRUNC: bool = false, CEXEC: bool = false, RCLOSE: bool = false, _7: u5 = 0, EXCL: bool = false, _: u19 = 0, }; |
ExecData |
pub const ExecData = struct { pub extern const etext: anyopaque; pub extern const edata: anyopaque; pub extern const end: anyopaque; }; |
brk_() |
/// Brk sets the system's idea of the lowest bss location not /// used by the program (called the break) to addr rounded up to /// the next multiple of 8 bytes. Locations not less than addr /// and below the stack pointer may cause a memory violation if /// accessed. -9front brk(2) pub fn brk_(addr: usize) i32 { return @intCast(syscall_bits.syscall1(.BRK_, addr)); } var bloc: usize = 0; var bloc_max: usize = 0; |
sbrk() |
pub fn sbrk(n: usize) usize { if (bloc == 0) { // we are at the start bloc = @intFromPtr(&ExecData.end); bloc_max = @intFromPtr(&ExecData.end); } const bl = std.mem.alignForward(usize, bloc, std.heap.pageSize()); const n_aligned = std.mem.alignForward(usize, n, std.heap.pageSize()); if (bl + n_aligned > bloc_max) { // we need to allocate if (brk_(bl + n_aligned) < 0) return 0; bloc_max = bl + n_aligned; } bloc = bloc + n_aligned; return bl; } |
Generated by zstd-live on 2025-08-12 12:37:57 UTC. |