commit 109c042c35cf3aafb821a3592801ee1a719b3bba
parent 18b065adf399b281dda30c3f86390c8426c188b6
Author: Sylvia Ivory <git@sivory.net>
Date: Wed, 4 Feb 2026 23:44:48 -0800
WIP Journal
Diffstat:
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 {