sylveos

Toy Operating System
Log | Files | Refs

commit 109c042c35cf3aafb821a3592801ee1a719b3bba
parent 18b065adf399b281dda30c3f86390c8426c188b6
Author: Sylvia Ivory <git@sivory.net>
Date:   Wed,  4 Feb 2026 23:44:48 -0800

WIP Journal

Diffstat:
Api/journal.zig | 150+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpi/root.zig | 1+
2 files changed, 151 insertions(+), 0 deletions(-)

diff --git a/pi/journal.zig b/pi/journal.zig @@ -0,0 +1,150 @@ +const std = @import("std"); + +const mem = @import("./mem.zig"); +// Kinda like std.log but journaling +// In the future this would use runtime formatting + +pub const LogLevel = enum(u8) { + // "The system is probably dead" + Emergency = 0, + // "A problem that requires immediate attention" + Alert = 1, + // Something has gone wrong, possibly recoverable + Error = 2, + // It is uncertain if something has gone wrong or not + Warning = 3, + // "Normal but perhaps noteworthy" + Notice = 4, + // General messages + Info = 5, + // Messages only useful for debugging + Debug = 6, + + pub fn text(comptime self: LogLevel) []const u8 { + return switch (self) { + .Emergency => "emergency", + .Alert => "alert", + .Error => "error", + .Warning => "warning", + .Notice => "notice", + .Info => "info", + .Debug => "debug", + }; + } + + pub fn text_short(comptime self: LogLevel) u8 { + return switch (self) { + .Emergency => '!', + .Alert => 'A', + .Error => 'E', + .Warning => 'W', + .Notice => 'N', + .Info => 'I', + .Debug => 'D', + }; + } +}; + +pub const LogWriter = struct { + node: std.SinglyLinkedList.Node, + writer: *std.Io.Writer, +}; + +var log_level: LogLevel = .Info; +var writers: std.SinglyLinkedList = .{ .first = null }; + +// TODO; shouldn't have static buffer +var buffer: [1024 * 1024]u8 = undefined; +var fba: std.heap.FixedBufferAllocator = .init(&buffer); + +pub inline fn set_log_level(level: LogLevel) void { + log_level = level; +} + +pub fn log(comptime level: LogLevel, comptime scope: []const u8, comptime format: []const u8, args: anytype) void { + const level_txt = comptime level.text_short(); + const prefix = if (scope.len == 0) ": " else scope ++ ": "; + + const cs = mem.enter_critical_section(); + defer cs.exit(); + + var head = writers.first; + while (head) |writer| { + const node: *LogWriter = @fieldParentPtr("node", writer); + + node.writer.print(level_txt ++ prefix ++ format ++ "\n", args) catch { + // TODO; queue write error + continue; + }; + + head = writer.next; + } +} + +pub fn push_writer(w: *std.Io.Writer) void { + var writer = try fba.allocator().create(LogWriter); + writer.writer = w; + writers.prepend(&writer.node); +} + +pub fn pop_writer(w: *std.Io.Writer) void { + var head = writers.first; + while (head) |writer| { + const node: *LogWriter = @fieldParentPtr("node", writer); + + if (node.writer == w) { + writers.remove(node); + return; + } + + head = writer.next; + } +} + +pub fn scoped(comptime scope: []const u8) type { + return struct { + pub fn emergency(comptime format: []const u8, args: anytype) void { + @branchHint(.cold); + log(.Emergency, scope, format, args); + } + + pub fn alert(comptime format: []const u8, args: anytype) void { + @branchHint(.cold); + log(.Alert, scope, format, args); + } + + pub fn err(comptime format: []const u8, args: anytype) void { + @branchHint(.cold); + log(.Error, scope, format, args); + } + + pub fn warn(comptime format: []const u8, args: anytype) void { + @branchHint(.cold); + log(.Warning, scope, format, args); + } + + pub fn notice(comptime format: []const u8, args: anytype) void { + @branchHint(.cold); + log(.Notice, scope, format, args); + } + + pub fn info(comptime format: []const u8, args: anytype) void { + @branchHint(.cold); + log(.Info, scope, format, args); + } + + pub fn debug(comptime format: []const u8, args: anytype) void { + @branchHint(.cold); + log(.Debug, scope, format, args); + } + }; +} + +const default = scoped(""); +pub const emergency = default.emergency; +pub const alert = default.alert; +pub const err = default.err; +pub const warning = default.warn; +pub const notice = default.notice; +pub const info = default.info; +pub const debug = default.debug; diff --git a/pi/root.zig b/pi/root.zig @@ -2,6 +2,7 @@ pub const Scheduler = @import("scheduler.zig"); pub const PSR = @import("./psr.zig").PSR; pub const interrupts = @import("./interrupts.zig"); +pub const journal = @import("./journal.zig"); pub const mem = @import("./mem.zig"); pub const devices = struct {