diff --git a/src/kern/log.zig b/src/kern/log.zig index 53c3d28..e4116ea 100644 --- a/src/kern/log.zig +++ b/src/kern/log.zig @@ -5,48 +5,25 @@ const pl = b.pl; const ke = b.ke; const ki = ke.private; -var console_lock = ke.SpinLock.init(); -var console_list: rtl.List = .{ .head = .{ .next = &console_list.head, .prev = &console_list.head } }; - -/// Represents a console device. -/// This is used as an output device. -pub const Console = struct { - last_seq: u64, - write: WriteFn, - link: rtl.List.Entry, - pub const WriteFn = *const fn (self: *Console, data: []const u8) void; -}; - -/// Register a console. -pub fn register_console(console: *Console) void { - const ipl = console_lock.acquire(); - console_list.insert_tail(&console.link); - console_lock.release(ipl); - - flush(); -} - -const ConsoleWriter = struct { +const DebugWriter = struct { interface: std.Io.Writer, - console: *Console, - pub fn init(console: *Console) ConsoleWriter { + pub fn init() DebugWriter { return .{ .interface = .{ .vtable = &.{ .drain = drain }, .buffer = &.{}, .end = 0, }, - .console = console, }; } - fn drain(w: *std.Io.Writer, data: []const []const u8, _: usize) std.Io.Writer.Error!usize { - const self: *ConsoleWriter = @fieldParentPtr("interface", w); - + fn drain(_: *std.Io.Writer, data: []const []const u8, _: usize) std.Io.Writer.Error!usize { var total_written: usize = 0; for (data) |slice| { - self.console.write(self.console, slice); + for (slice) |byte| { + pl.impl.debug_write(byte); + } total_written += slice.len; } @@ -56,32 +33,6 @@ const ConsoleWriter = struct { var ringbuffer = ki.log_ring.RingBuffer(14, 5).init(); -fn flush() void { - var buf: [512]u8 = undefined; - - // Note: we trylock here because if the lock is already held, that means - // someone else is already flushing the logs. - if (console_lock.try_acquire()) |ipl| { - var it = console_list.iterator(); - - while (it.next()) : (it.advance()) { - const console: *Console = @fieldParentPtr("link", it.get()); - var writer = ConsoleWriter.init(console); - - while (true) { - const info = ringbuffer.read(console.last_seq, &buf) catch break; - - writer.interface.print("[{:>5}.{:06}] ", .{ info.timestamp / std.time.ns_per_s, info.timestamp / std.time.ns_per_us }) catch break; - console.write(console, buf[0..info.length]); - - console.last_seq = info.sequence + 1; - } - } - - console_lock.release(ipl); - } -} - pub fn log( comptime level: std.log.Level, comptime scope: @EnumLiteral(), @@ -91,17 +42,25 @@ pub fn log( _ = level; _ = scope; - var discarder: std.Io.Writer.Discarding = .init(&.{}); - discarder.writer.print(fmt ++ "\n", args) catch return; + // Calculate the length required. + const required_len = std.fmt.count(fmt ++ "\n", args); - var res = ringbuffer.reserve(discarder.fullCount()) catch return; + // Reserve space in the ring buffer. + var res = ringbuffer.reserve(required_len) catch return; res.info.timestamp = ke.time.read_time_nano(); - res.info.length = @truncate(discarder.fullCount()); + res.info.length = @truncate(required_len); + // Format the log message into the reserved buffer. res.buf = std.fmt.bufPrint(res.buf, fmt ++ "\n", args) catch return; ringbuffer.publish(res); - flush(); + // TODO: for now, we print to the platform's debug output immediately. + // In the future, we should instead set an event that would get triggered in Ex, + // which would consume the ringbuffer from multiple consoles in a separate thread. + var writer = DebugWriter.init(); + + writer.interface.print("[{:>5}.{:06}] ", .{ res.info.timestamp / std.time.ns_per_s, res.info.timestamp / std.time.ns_per_us }) catch return; + _ = writer.interface.writeAll(res.buf[0..res.info.length]) catch return; } diff --git a/src/platform/um/impl.zig b/src/platform/um/impl.zig index 90933ea..65daef7 100644 --- a/src/platform/um/impl.zig +++ b/src/platform/um/impl.zig @@ -39,8 +39,8 @@ pub threadlocal var my_cpu: *ke.Cpu = undefined; pub fn devices_init() void {} -fn debug_write(_: *ke.Console, buf: []const u8) void { - _ = linux.write(1, buf.ptr, @intCast(buf.len)); +pub fn debug_write(char: u8) void { + _ = linux.write(linux.STDERR_FILENO, @ptrCast(&char), 1); } pub const arm_timer = timer.arm_timer; @@ -60,12 +60,6 @@ const bootstrap_offsets = [1]usize{0}; pub var cpu_offsets: []usize = undefined; -var early_console: ke.Console = .{ - .write = debug_write, - .last_seq = 0, - .link = undefined, -}; - pub fn early_init() linksection(b.init) void { // Ensure we can use per-cpu data. cpu_offsets = @constCast(&bootstrap_offsets); @@ -106,8 +100,6 @@ pub fn early_init() linksection(b.init) void { b.kernel_heap_base = heap_base; std.log.info("um: kernel heap lives at {X}", .{heap_base}); - - ke.log.register_console(&early_console); } fn sigusr1_handler(_: posix.SIG, _: *const posix.siginfo_t, _: ?*anyopaque) callconv(.c) void {