Files
Zag/src/ex/console.zig
T
2026-08-19 18:04:12 -04:00

134 lines
3.0 KiB
Zig

//! Logging (for now) consoles.
const std = @import("std");
const r = @import("root");
const rtl = @import("rtl");
const ke = r.ke;
const ps = r.ps;
const ex = r.ex;
pub const Console = struct {
link: rtl.List.Entry,
write: *const fn (ctx: ?*anyopaque, slice: []const u8) void,
ctx: ?*anyopaque,
};
const ConWriter = struct {
interface: std.Io.Writer,
console: *Console,
pub fn init(console: *Console) ConWriter {
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: *ConWriter = @fieldParentPtr("interface", w);
var total_written: usize = 0;
for (data) |slice| {
self.console.write(self.console.ctx, slice);
total_written += slice.len;
}
return total_written;
}
};
var console_list: rtl.List = undefined;
var console_lock: ke.Mutex = .init();
var last_seq: usize = 0;
fn write_on(buf: []u8, rec: anytype, console: *Console) void {
var writer = ConWriter.init(console);
writer.interface.writeAll(buf[0..rec.length]) catch unreachable;
}
fn drain_from_on(seq: usize, console: *Console) usize {
var cur_seq: usize = seq;
var buf: [1024]u8 = undefined;
while (true) {
const rec = ke.log.ringbuffer.read(cur_seq, &buf) catch break;
write_on(&buf, rec, console);
cur_seq += 1;
}
return cur_seq;
}
fn drain_from_all(seq: usize) usize {
var cur_seq: usize = seq;
var buf: [1024]u8 = undefined;
while (true) {
const rec = ke.log.ringbuffer.read(cur_seq, &buf) catch break;
console_lock.acquire();
var it = console_list.iterator();
while (it.next()) : (it.advance()) {
const console: *Console = @fieldParentPtr("link", it.get());
write_on(&buf, rec, console);
}
console_lock.release();
cur_seq += 1;
}
return cur_seq;
}
fn worker(_: ?*anyopaque) void {
while (true) {
_ = ke.wait.wait_one(&ke.log.event.hdr, "console_worker", .{}) catch
unreachable;
ke.log.event.reset();
last_seq = drain_from_all(last_seq);
}
}
pub fn write(buf: []const u8) void {
console_lock.acquire();
var it = console_list.iterator();
while (it.next()) : (it.advance()) {
const console: *Console = @fieldParentPtr("link", it.get());
console.write(console.ctx, buf);
}
console_lock.release();
}
pub fn register(cons: *Console) void {
// Drain all logs until now.
_ = drain_from_on(0, cons);
console_lock.acquire();
console_list.insert_tail(&cons.link);
console_lock.release();
}
pub fn init() void {
console_list.init();
const td = ps.thread.create_kernel(
.Default,
worker,
null,
) catch @panic("handle me");
ke.sched.enqueue(&td.kern);
}