sylveos

Toy Operating System
Log | Files | Refs

commit 9beb46c3b84eb98217324f06fb4a752e23665930
parent 46947c53efa2dd716ba099327a0515215edd40dd
Author: Sylvia Ivory <git@sivory.net>
Date:   Thu, 22 Jan 2026 20:15:55 -0800

Add profiler lab (needs new root)

Diffstat:
Msrc/devices/timer.zig | 4++++
Asrc/labs/4-profiler.zig | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main.zig | 45+--------------------------------------------
3 files changed, 60 insertions(+), 44 deletions(-)

diff --git a/src/devices/timer.zig b/src/devices/timer.zig @@ -100,6 +100,10 @@ noinline fn timer_handler(pc: usize) void { mem.barrier(.Write); // Sync before restoring } +pub inline fn set_tick(tick: *const fn (usize) void) void { + tick_fn = tick; +} + pub inline fn get_count() u32 { return count; } diff --git a/src/labs/4-profiler.zig b/src/labs/4-profiler.zig @@ -0,0 +1,55 @@ +const std = @import("std"); +const interrupts = @import("pi").interrupts; + +const uart = @import("devices/mini-uart.zig"); +const clock = @import("devices/clock.zig"); +const timer = @import("devices/timer.zig"); + +// 1Mb +var buffer: [1024 * 1024]u8 = undefined; +var fba: std.heap.FixedBufferAllocator = undefined; +var hist: std.AutoHashMap(usize, usize) = undefined; +var enabled = true; + +extern const __code_start__: u32; +extern const __code_end__: u32; + +fn tick(pc: usize) void { + if (!enabled) return; + + const res = hist.getOrPutValue(pc, 0) catch unreachable; + const new_value = res.value_ptr.* + 1; + + hist.put(pc, new_value) catch unreachable; +} + +fn dump(min: usize) void { + enabled = false; + uart.writer.print("call profile:\n", .{}) catch {}; + var iterator = hist.iterator(); + + while (iterator.next()) |entry| { + if (entry.value_ptr.* < min) continue; + uart.writer.print(" 0x{X}: {d}\n", .{ entry.key_ptr.*, entry.value_ptr.* }) catch {}; + } + enabled = true; +} + +pub fn main() !void { + timer.initialize(.Sixteen, 0x100); + timer.set_tick(tick); + + fba = .init(&buffer); + hist = .init(fba.allocator()); + + interrupts.enable_interrupts(); + + var iter: usize = 0; + while (timer.get_count() < 200) { + try uart.writer.print("iter={d}: count = {d}, period = {d}us, 0x{x}\n", .{ iter, timer.get_count(), timer.get_period(), timer.get_period() }); + iter += 1; + if (iter % 10 == 0) { + dump(2); + } + } +} diff --git a/src/main.zig b/src/main.zig @@ -1,44 +1 @@ -const interrupts = @import("pi").interrupts; - -const uart = @import("devices/mini-uart.zig"); -const clock = @import("devices/clock.zig"); -const timer = @import("devices/timer.zig"); - -pub fn main() !void { - try uart.writer.print("entered main safely...\n", .{}); - - timer.initialize(.Sixteen, 0x100); - - try uart.writer.print("initialized timer...\n", .{}); - - interrupts.enable_interrupts(); - - try uart.writer.print("enabled interrupts...\n", .{}); - - const start = clock.current_count(); - var iter: u32 = 0; - const N = 20; - - while (timer.get_count() < N) { - try uart.writer.print("iter={d}: count={d}, time between interrupts = {d} usec (0x{x})\n", .{ - iter, - timer.get_count(), - timer.get_period(), - timer.get_period(), - }); - iter += 1; - } - - const total = clock.current_count() - start; - const total_sec = total / (1000 * 1000); - const total_ms = (total / 1000) % 10000; - const total_us = (total % 1000); - - try uart.writer.print( - \\ total iterations: {} - \\ total interrupts: {} - \\ iterations / interrupt: {} - \\ average period: {} - \\ total execution time: {}s.{}ms.{}us - , .{ iter, N, iter / N, timer.get_period_sum() / (N - 1), total_sec, total_ms, total_us }); -} +fn main() void {}