mirror of
https://github.com/rdmsr/zag.git
synced 2026-10-27 13:58:20 +00:00
108 lines
2.6 KiB
Zig
108 lines
2.6 KiB
Zig
//! Kernel logging.
|
|
|
|
const std = @import("std");
|
|
const config = @import("config");
|
|
const r = @import("root");
|
|
|
|
const pl = r.pl;
|
|
const ke = r.ke;
|
|
const kep = ke.private;
|
|
const bv = r.bv;
|
|
|
|
var out_lock: ke.SpinLock = undefined;
|
|
|
|
const DebugWriter = struct {
|
|
interface: std.Io.Writer,
|
|
|
|
pub fn init() DebugWriter {
|
|
return .{
|
|
.interface = .{
|
|
.vtable = &.{ .drain = drain },
|
|
.buffer = &.{},
|
|
.end = 0,
|
|
},
|
|
};
|
|
}
|
|
|
|
fn drain(
|
|
_: *std.Io.Writer,
|
|
data: []const []const u8,
|
|
_: usize,
|
|
) std.Io.Writer.Error!usize {
|
|
var total_written: usize = 0;
|
|
for (data) |slice| {
|
|
for (slice) |byte| {
|
|
bv.write_char(byte);
|
|
pl.impl.debug_write(byte);
|
|
}
|
|
total_written += slice.len;
|
|
}
|
|
|
|
return total_written;
|
|
}
|
|
};
|
|
|
|
// Messages are on average 2^5 = 32 bytes.
|
|
const avg_msg_size_bits = 5;
|
|
|
|
pub var ringbuffer = kep.log_ring.RingBuffer(
|
|
config.log_buffer_shift,
|
|
avg_msg_size_bits,
|
|
).init();
|
|
|
|
pub var event: ke.Event = undefined;
|
|
|
|
pub fn init() void {
|
|
out_lock = ke.SpinLock.init("");
|
|
event.init(.Notification);
|
|
}
|
|
|
|
pub fn force_release_lock() void {
|
|
out_lock.release_no_ipl();
|
|
}
|
|
|
|
pub fn log(
|
|
comptime level: std.log.Level,
|
|
comptime scope: @EnumLiteral(),
|
|
comptime fmt: []const u8,
|
|
args: anytype,
|
|
) void {
|
|
_ = level;
|
|
|
|
const scope_str = if (scope == .default) "" else @tagName(scope) ++ ": ";
|
|
|
|
// Calculate the length required.
|
|
const required_len = std.fmt.count(scope_str ++ fmt ++ "\n", args);
|
|
|
|
// Reserve space in the ring buffer.
|
|
var res = ringbuffer.reserve(required_len) catch return;
|
|
|
|
res.info.timestamp = ke.time.read_time();
|
|
res.info.length = @truncate(required_len);
|
|
|
|
// Format the log message into the reserved buffer.
|
|
res.buf = std.fmt.bufPrint(res.buf, scope_str ++ fmt ++ "\n", args) catch
|
|
return;
|
|
|
|
ringbuffer.publish(res);
|
|
|
|
// Signal whomever is waiting on logs to get published.
|
|
if (@intFromEnum(ke.ipl.current()) <= @intFromEnum(ke.Ipl.Dispatch)) {
|
|
event.signal();
|
|
}
|
|
|
|
var writer = DebugWriter.init();
|
|
|
|
const ipl = out_lock.acquire_at(.High);
|
|
defer out_lock.release(ipl);
|
|
|
|
writer.interface.print(
|
|
"[{:>5}.{:06}] ",
|
|
.{
|
|
res.info.timestamp.value / std.time.ns_per_s,
|
|
(res.info.timestamp.value % std.time.ns_per_s) / std.time.ns_per_us,
|
|
},
|
|
) catch return;
|
|
_ = writer.interface.writeAll(res.buf[0..res.info.length]) catch return;
|
|
}
|