feat: use per-cpu sections

This commit is contained in:
Loïc Grégoire
2026-03-23 20:29:34 -04:00
parent 33c796c958
commit 020e81f34b
14 changed files with 235 additions and 117 deletions
+24 -14
View File
@@ -6,7 +6,7 @@ const ki = ke.private;
/// Interrupt priority level (IPL)
pub const Ipl = enum(u8) {
/// All interrupts enabled.
Zero = 0,
Passive = 0,
/// Preemption disabled.
Dispatch = 1,
/// Device interrupts disabled.
@@ -19,9 +19,14 @@ pub const Ipl = enum(u8) {
}
};
/// Bitmask of pending software interrupts on this CPU.
const pending_softints = ke.CpuLocal(std.atomic.Value(u8), .init(0));
/// Raise IPL to `new`.
/// Panics if the current IPL is higher than requested.
pub fn raise(new: Ipl) Ipl {
const ints = ki.impl.disable_interrupts();
var cpu = ke.curcpu();
const old = cpu.ipl;
@@ -35,12 +40,15 @@ pub fn raise(new: Ipl) Ipl {
cpu.ipl = new;
ki.impl.restore_interrupts(ints);
return old;
}
/// Lower IPL to `new`.
/// Panics if the current IPL is lower than requested.
pub fn lower(new: Ipl) void {
const ints = ki.impl.disable_interrupts();
var cpu = ke.curcpu();
const old = cpu.ipl;
@@ -49,21 +57,23 @@ pub fn lower(new: Ipl) void {
}
if (@intFromEnum(new) <= @intFromEnum(Ipl.get_max_software()) and @intFromEnum(old) > @intFromEnum(Ipl.get_max_software())) {
ki.impl.set_hardware_ipl(.Zero);
}
if (@intFromEnum(new) < @intFromEnum(Ipl.Dispatch) and is_softint_pending(cpu, .Dispatch)) {
ki.dpc.dispatch(cpu);
ki.impl.set_hardware_ipl(.Passive);
}
cpu.ipl = new;
ki.impl.restore_interrupts(ints);
if (@intFromEnum(new) < @intFromEnum(Ipl.Dispatch) and is_softint_pending(.Dispatch)) {
ki.dpc.dispatch(cpu);
}
}
comptime {
if (!@hasDecl(ki.impl, "set_hardware_ipl")) @compileError("impl must provide set_hardware_ipl()");
}
/// Set the hardware IPL to `new`
/// Set the hardware IPL to `new`.
pub fn set_hardware(new: Ipl) Ipl {
var cpu = ke.curcpu();
const old = cpu.ipl;
@@ -75,22 +85,22 @@ pub fn set_hardware(new: Ipl) Ipl {
return old;
}
/// Mark a software interrupt of IPL `ipl` on `cpu` as pending
/// Mark a software interrupt of IPL `ipl` on `cpu` as pending.
pub fn set_softint_pending(cpu: *ke.Cpu, ipl: Ipl) void {
std.debug.assert(@intFromEnum(ipl) <= @intFromEnum(Ipl.Dispatch));
_ = cpu.pending_softints.bitSet(@intCast(@intFromEnum(ipl)), .monotonic);
_ = pending_softints.remote(cpu).bitSet(@intCast(@intFromEnum(ipl)), .monotonic);
}
/// Mark a software interrupt of IPL `ipl` on `cpu` as handled
/// Mark a software interrupt of IPL `ipl` on `cpu` as handled.
pub fn clear_softint_pending(cpu: *ke.Cpu, ipl: Ipl) void {
std.debug.assert(@intFromEnum(ipl) <= @intFromEnum(Ipl.Dispatch));
_ = cpu.pending_softints.bitReset(@intCast(@intFromEnum(ipl)), .monotonic);
_ = pending_softints.remote(cpu).bitReset(@intCast(@intFromEnum(ipl)), .monotonic);
}
/// Check whether a software interrupt of IPL `ipl` on `cpu` is pending
pub fn is_softint_pending(cpu: *ke.Cpu, ipl: Ipl) bool {
/// Check whether a software interrupt of IPL `ipl` on the current CPU is pending.
pub fn is_softint_pending(ipl: Ipl) bool {
std.debug.assert(@intFromEnum(ipl) <= @intFromEnum(Ipl.Dispatch));
const shift: u3 = @intCast(@intFromEnum(ipl));
const bit: u8 = @as(u8, 1) << shift;
return cpu.pending_softints.load(.monotonic) & bit != 0;
return pending_softints.local().load(.monotonic) & bit != 0;
}