Replace the linear keep-earliest RAM buffer with a 512 KiB ring of framed records (log-ring.zig, host-tested): every debug_write becomes one record per payload line, stamped by the kernel with the sender's pid, task name (its binary path), level, per-boot sequence number, and monotonic timestamp. Attribution is structural — a payload cannot forge another sender's tag, and newline injection lands inside the forger's own next record. Oldest records are overwritten when full; sequence gaps make the loss countable. debug_write gains a level argument (err/warn/info/debug/raw; old two-arg callers clamp to raw). klog_read becomes a stream-offset read that fails once the cursor falls behind the ring's tail; the new klog_status (#45) returns the cursors plus the boot wall-clock anchor — what the logger service will name per-boot log directories with. The log now guards itself with a dedicated spinlock (BKL -> log lock order, never the reverse); panic paths use a bounded try-acquire and fall back to sinks-only. Serial rendering keeps the historical transcript byte-identical for kernel and legacy raw output; leveled records get a kernel-rendered name prefix. log-flush/init's interim drains start at the ring tail and write framed records until the logger service replaces them.
33 lines
1.4 KiB
Zig
33 lines
1.4 KiB
Zig
//! Wall-clock time: the CMOS real-time clock read once at boot and anchored to the
|
|
//! monotonic clock, so a query is a cheap arithmetic offset — no per-call CMOS poll,
|
|
//! no lock, no SMP hazard on the shared 0x70/0x71 ports.
|
|
//!
|
|
//! Wall-clock *seconds* are mechanism the kernel owns, exactly like the monotonic
|
|
//! clock ([[time-architecture]]): reading the hardware's value is not policy.
|
|
//! Calendars, timezones, and formatting layer on top in user space. It exists so the
|
|
//! filesystem can stamp real timestamps (mtime) — see docs/zig-self-hosting.md.
|
|
|
|
const architecture = @import("architecture");
|
|
|
|
var boot_unix_seconds: u64 = 0;
|
|
var boot_nanos: u64 = 0;
|
|
|
|
/// Read the RTC once and anchor it to the monotonic clock. Call at boot, after the
|
|
/// monotonic clock is calibrated.
|
|
pub fn init() void {
|
|
boot_unix_seconds = architecture.readRtcUnixSeconds();
|
|
boot_nanos = architecture.nanos();
|
|
}
|
|
|
|
/// The current wall-clock time in Unix epoch seconds (UTC): the boot RTC value plus
|
|
/// the monotonic time elapsed since. Zero until `init` runs.
|
|
pub fn nowSeconds() u64 {
|
|
return boot_unix_seconds + (architecture.nanos() -% boot_nanos) / 1_000_000_000;
|
|
}
|
|
|
|
/// The wall-clock time of boot itself (the RTC anchor) — what klog_status hands
|
|
/// the logger service to name a per-boot log directory. Zero until `init` runs.
|
|
pub fn bootSeconds() u64 {
|
|
return boot_unix_seconds;
|
|
}
|