From 782196275b6a435bf9b64df77978c5c87caf2549 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Gr=C3=A9goire?= Date: Sat, 18 Jul 2026 16:45:32 -0400 Subject: [PATCH] mm+ke: make shootdowns use HandoffList --- src/kern/init.zig | 1 - src/kern/shootdown.zig | 10 +++------- src/mm/tlb.zig | 28 +++++++++++++++++----------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/kern/init.zig b/src/kern/init.zig index 0ff8d1f..772238a 100644 --- a/src/kern/init.zig +++ b/src/kern/init.zig @@ -19,7 +19,6 @@ pub fn init(boot_info: *r.BootInfo) linksection(r.init) void { ki.log.init(); ki.cpu.init_cpu(0); ki.turnstile.init_turnstiles(); - ki.shootdown.init(); thread0.init(@intFromPtr(&stack), r.kib(16), ke.Thread.Priority.idle_low, ki.sched.idle, null); thread0.priority = 0; diff --git a/src/kern/shootdown.zig b/src/kern/shootdown.zig index bde9708..dc7efe1 100644 --- a/src/kern/shootdown.zig +++ b/src/kern/shootdown.zig @@ -14,7 +14,7 @@ pub const ShootdownState = struct { /// This is used as a counter when the request is outstanding, /// otherwise it is set to the `slot_*` values below. state: std.atomic.Value(u16), - link: rtl.List.Entry, + link: ?*anyopaque, /// Base virtual address of the shootdown. base: r.VAddr, /// Number of pages to flush. @@ -42,7 +42,7 @@ const slot_free: u16 = std.math.maxInt(u16); const slot_reserved: u16 = std.math.maxInt(u16) - 1; const percpu = ke.CpuLocal(PerCpu, undefined); -pub var shootdowns: ke.Queue = undefined; +pub var shootdowns: rtl.HandoffList = undefined; var sync_counter: std.atomic.Value(usize) = .init(0); var sync_addr: r.VAddr = 0; @@ -149,7 +149,7 @@ pub fn process_shootdowns() void { flush_range(state.base, state.npages); if (state.state.fetchSub(1, .release) == 1) { - shootdowns.insert(&state.link, .Tail); + shootdowns.insert(&state.link); } } } @@ -189,7 +189,3 @@ pub fn submit(state: ShootdownState, target_mask: ke.CpuMask) !void { percpu.remote(@truncate(bit)).senders.set(curcpu, .release); } } - -pub fn init() void { - shootdowns.init(ke.ncpus); -} diff --git a/src/mm/tlb.zig b/src/mm/tlb.zig index 009a0d6..154cb9a 100644 --- a/src/mm/tlb.zig +++ b/src/mm/tlb.zig @@ -2,19 +2,26 @@ const r = @import("root"); const std = @import("std"); +const rtl = @import("rtl"); const ke = r.ke; const mm = r.mm; const mi = mm.private; const ps = r.ps; +const ex = r.ex; pub var sync_shootdowns: std.atomic.Value(usize) = .init(0); pub var async_shootdowns: std.atomic.Value(usize) = .init(0); pub var sent_shootdowns: std.atomic.Value(usize) = .init(0); +var work_item: ex.WorkItem = undefined; + /// Reclaim the memory associated with a state. /// This can only be done when all CPUs have flushed their TLB. -fn reclaim_state(state: *ke.ShootdownState) void { +fn reclaim_state(obj: *anyopaque, _: ?*anyopaque) void { + const link: *?*anyopaque = @ptrCast(@alignCast(obj)); + const state: *ke.ShootdownState = @fieldParentPtr("link", link); + const space: *mm.Space = @ptrFromInt(state.payload[0]); const pfn_list: mi.PfnList = @bitCast(state.payload[1]); const base = state.base; @@ -36,13 +43,8 @@ fn reclaim_state(state: *ke.ShootdownState) void { state.release(); } -fn worker_thread(_: ?*anyopaque) void { - while (true) { - const entry = ke.shootdown.shootdowns.remove(); - const state: *ke.ShootdownState = @fieldParentPtr("link", entry); - - reclaim_state(state); - } +fn reap_pages(_: ?*anyopaque) void { + ke.shootdown.shootdowns.process(reclaim_state, null); } /// Unmap and flush a virtual range on the given space. @@ -86,7 +88,11 @@ pub fn reclaim_range(space: *mm.Space, va: r.VAddr, size: usize) void { }; } -pub fn init() void { - const td = ps.thread.create_kernel(ke.Thread.Priority.default, worker_thread, null) catch unreachable; - ke.sched.enqueue(&td.kern); +fn activation(_: *rtl.HandoffList) void { + ex.workqueue.enqueue(&work_item); +} + +pub fn init() void { + ke.shootdown.shootdowns.* = .init(activation); + work_item.init(.High, reap_pages, null); }