diff --git a/std/mem.zig b/std/mem.zig index 07521bfcb8..97cb35ae65 100644 --- a/std/mem.zig +++ b/std/mem.zig @@ -354,7 +354,7 @@ pub fn startsWith(comptime T: type, haystack: []const T, needle: []const T) bool return if (needle.len > haystack.len) false else eql(T, haystack[0 .. needle.len], needle); } -const SplitIterator = struct { +pub const SplitIterator = struct { buffer: []const u8, split_bytes: []const u8, index: usize, diff --git a/std/os/zen.zig b/std/os/zen.zig index b10b870d17..9e1944dc6d 100644 --- a/std/os/zen.zig +++ b/std/os/zen.zig @@ -1,20 +1,121 @@ -////////////////////////////// -//// Reserved mailboxes //// -////////////////////////////// +////////////////////////// +//// IPC structures //// +////////////////////////// -pub const MBOX_TERMINAL = 1; +pub const Message = struct { + sender: MailboxId, + receiver: MailboxId, + type: usize, + payload: usize, + + pub fn from(mailbox_id: &const MailboxId) Message { + return Message { + .sender = MailboxId.Undefined, + .receiver = *mailbox_id, + .type = 0, + .payload = 0, + }; + } + + pub fn to(mailbox_id: &const MailboxId, msg_type: usize) Message { + return Message { + .sender = MailboxId.This, + .receiver = *mailbox_id, + .type = msg_type, + .payload = 0, + }; + } + + pub fn withData(mailbox_id: &const MailboxId, msg_type: usize, payload: usize) Message { + return Message { + .sender = MailboxId.This, + .receiver = *mailbox_id, + .type = msg_type, + .payload = payload, + }; + } +}; + +pub const MailboxId = union(enum) { + Undefined, + This, + Kernel, + Port: u16, + Thread: u16, +}; + + +////////////////////////////////////// +//// Ports reserved for servers //// +////////////////////////////////////// + +pub const Server = struct { + pub const Keyboard = MailboxId { .Port = 0 }; + pub const Terminal = MailboxId { .Port = 1 }; +}; + + +//////////////////////// +//// POSIX things //// +//////////////////////// + +// Standard streams. +pub const STDIN_FILENO = 0; +pub const STDOUT_FILENO = 1; +pub const STDERR_FILENO = 2; + +// FIXME: let's borrow Linux's error numbers for now. +pub const getErrno = @import("linux/index.zig").getErrno; +use @import("linux/errno.zig"); + +// TODO: implement this correctly. +pub fn read(fd: i32, buf: &u8, count: usize) usize { + switch (fd) { + STDIN_FILENO => { + var i: usize = 0; + while (i < count) : (i += 1) { + send(Message.to(Server.Keyboard, 0)); + + var message = Message.from(MailboxId.This); + receive(&message); + + buf[i] = u8(message.payload); + } + }, + else => unreachable, + } + return count; +} + +// TODO: implement this correctly. +pub fn write(fd: i32, buf: &const u8, count: usize) usize { + switch (fd) { + STDOUT_FILENO, STDERR_FILENO => { + var i: usize = 0; + while (i < count) : (i += 1) { + send(Message.withData(Server.Terminal, 1, buf[i])); + } + }, + else => unreachable, + } + return count; +} /////////////////////////// //// Syscall numbers //// /////////////////////////// -pub const SYS_exit = 0; -pub const SYS_createMailbox = 1; -pub const SYS_send = 2; -pub const SYS_receive = 3; -pub const SYS_map = 4; -pub const SYS_createThread = 5; +pub const Syscall = enum(usize) { + exit = 0, + createPort = 1, + send = 2, + receive = 3, + subscribeIRQ = 4, + inb = 5, + map = 6, + createThread = 7, +}; //////////////////// @@ -22,28 +123,39 @@ pub const SYS_createThread = 5; //////////////////// pub fn exit(status: i32) noreturn { - _ = syscall1(SYS_exit, @bitCast(usize, isize(status))); + _ = syscall1(Syscall.exit, @bitCast(usize, isize(status))); unreachable; } -pub fn createMailbox(id: u16) void { - _ = syscall1(SYS_createMailbox, id); +pub fn createPort(mailbox_id: &const MailboxId) void { + _ = switch (*mailbox_id) { + MailboxId.Port => |id| syscall1(Syscall.createPort, id), + else => unreachable, + }; } -pub fn send(mailbox_id: u16, data: usize) void { - _ = syscall2(SYS_send, mailbox_id, data); +pub fn send(message: &const Message) void { + _ = syscall1(Syscall.send, @ptrToInt(message)); } -pub fn receive(mailbox_id: u16) usize { - return syscall1(SYS_receive, mailbox_id); +pub fn receive(destination: &Message) void { + _ = syscall1(Syscall.receive, @ptrToInt(destination)); +} + +pub fn subscribeIRQ(irq: u8, mailbox_id: &const MailboxId) void { + _ = syscall2(Syscall.subscribeIRQ, irq, @ptrToInt(mailbox_id)); +} + +pub fn inb(port: u16) u8 { + return u8(syscall1(Syscall.inb, port)); } pub fn map(v_addr: usize, p_addr: usize, size: usize, writable: bool) bool { - return syscall4(SYS_map, v_addr, p_addr, size, usize(writable)) != 0; + return syscall4(Syscall.map, v_addr, p_addr, size, usize(writable)) != 0; } pub fn createThread(function: fn()void) u16 { - return u16(syscall1(SYS_createThread, @ptrToInt(function))); + return u16(syscall1(Syscall.createThread, @ptrToInt(function))); } @@ -51,20 +163,20 @@ pub fn createThread(function: fn()void) u16 { //// Syscall stubs //// ///////////////////////// -pub inline fn syscall0(number: usize) usize { +inline fn syscall0(number: Syscall) usize { return asm volatile ("int $0x80" : [ret] "={eax}" (-> usize) : [number] "{eax}" (number)); } -pub inline fn syscall1(number: usize, arg1: usize) usize { +inline fn syscall1(number: Syscall, arg1: usize) usize { return asm volatile ("int $0x80" : [ret] "={eax}" (-> usize) : [number] "{eax}" (number), [arg1] "{ecx}" (arg1)); } -pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) usize { +inline fn syscall2(number: Syscall, arg1: usize, arg2: usize) usize { return asm volatile ("int $0x80" : [ret] "={eax}" (-> usize) : [number] "{eax}" (number), @@ -72,7 +184,7 @@ pub inline fn syscall2(number: usize, arg1: usize, arg2: usize) usize { [arg2] "{edx}" (arg2)); } -pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize { +inline fn syscall3(number: Syscall, arg1: usize, arg2: usize, arg3: usize) usize { return asm volatile ("int $0x80" : [ret] "={eax}" (-> usize) : [number] "{eax}" (number), @@ -81,7 +193,7 @@ pub inline fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usi [arg3] "{ebx}" (arg3)); } -pub inline fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { +inline fn syscall4(number: Syscall, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { return asm volatile ("int $0x80" : [ret] "={eax}" (-> usize) : [number] "{eax}" (number), @@ -91,7 +203,7 @@ pub inline fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg [arg4] "{esi}" (arg4)); } -pub inline fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, +inline fn syscall5(number: Syscall, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { return asm volatile ("int $0x80" @@ -104,7 +216,7 @@ pub inline fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, [arg5] "{edi}" (arg5)); } -pub inline fn syscall6(number: usize, arg1: usize, arg2: usize, arg3: usize, +inline fn syscall6(number: Syscall, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize, arg6: usize) usize { return asm volatile ("int $0x80"