From b89ee0e3e556750ef4591632a72b83df8d38e4ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Gr=C3=A9goire?= Date: Tue, 24 Mar 2026 22:22:26 -0400 Subject: [PATCH] fix(ke): fix various scheduler bugs --- src/kern/sched.zig | 15 ++++++++------- src/kern/thread.zig | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/kern/sched.zig b/src/kern/sched.zig index 13932c1..0cd1128 100644 --- a/src/kern/sched.zig +++ b/src/kern/sched.zig @@ -188,7 +188,7 @@ pub fn clock(_: ?*anyopaque) void { // Advance the insert index every tick, while keeping a separation of 1 with runidx. // This ensures fairness. if (sched_cpu.runidx == sched_cpu.insidx) { - sched_cpu.insidx = (sched_cpu.insidx) % runqueues_n; + sched_cpu.insidx = (sched_cpu.insidx + 1) % runqueues_n; } if (curtd.priority_class == .Batch) { @@ -243,7 +243,7 @@ pub fn unblock(td: *ke.Thread) void { td.sleep_time = (ke.timecounter.read_time_nano() - td.sleep_start) / std.time.ns_per_ms; - if (td.sleep_time >= config.CONFIG_SCHED_TIMESLICE and .priority_class == .Batch) { + if (td.sleep_time >= config.CONFIG_SCHED_TIMESLICE and td.priority_class == .Batch) { // If we have slept for more than a tick, update interactivity. clamp_time(td); recompute_priority(td); @@ -311,7 +311,7 @@ fn pick_realtime_thread(cpu: *PerCpu, minprio: u8, migrate: bool) ?*ke.Thread { // Search higher priority queues first. var i: usize = ke.Thread.Priority.max; - qloop: while (i >= minprio) : (i -= 1) { + qloop: while (i >= minprio and i > 0) : (i -= 1) { const bit = (@as(u64, 1) << @intCast(i)); if (runq.status & bit == 0) { @@ -345,6 +345,8 @@ fn pick_realtime_thread(cpu: *PerCpu, minprio: u8, migrate: bool) ?*ke.Thread { // Queue is now empty, clear its bit. runq.status &= ~bit; } + + return td; } return null; @@ -415,7 +417,7 @@ fn pick_idle_thread(cpu: *PerCpu, migrate: bool) ?*ke.Thread { // Just get the first thread from the queue. const td: *ke.Thread = @fieldParentPtr("runq_link", cpu.idle_queue.first()); - if (!migrate and td.pinned) { + if (!(migrate and td.pinned)) { // We can safely remove it. td.runq_link.remove(); } @@ -429,7 +431,6 @@ fn insert_in_list(list: *rtl.List, link: *rtl.List.Entry, head: bool) void { // Insert a thread into its respective queue. fn insert_in_queue(cpu: *PerCpu, td: *ke.Thread, head: bool) void { - std.debug.assert(td.lock.is_locked()); std.debug.assert(cpu.queues_lock.is_locked()); if (td.priority_class == .Realtime or td.interactive) { @@ -629,7 +630,7 @@ fn should_preempt_cpu(td: *ke.Thread, cpu: *ke.Cpu) bool { // Enqueue a thread on a CPU. fn enqueue_on_cpu(cpu: *ke.Cpu, td: *ke.Thread) void { - var c = percpu_data.local(); + var c = percpu_data.remote(cpu); c.queues_lock.acquire_no_ipl(); @@ -810,7 +811,7 @@ fn find_most_loaded(exclude: ?*ke.CpuMask) ?*ke.Cpu { const cpu = ke.cpus[i]; const load = percpu_data.remote(cpu).load.load(.monotonic); - if (most == null or load > most_load) { + if (most == null) { most = cpu; most_load = load; } else if (load > most_load) { diff --git a/src/kern/thread.zig b/src/kern/thread.zig index e70546e..94ccf8e 100644 --- a/src/kern/thread.zig +++ b/src/kern/thread.zig @@ -99,7 +99,7 @@ pub const Thread = struct { pub fn init(thread: *Thread, stack: b.VAddr, stack_size: usize, entry: *const fn (?*anyopaque) void, arg: ?*anyopaque) void { thread.* = .{ .context = .init(stack, stack_size, entry, arg), - .lock = ke.SpinLock.init(), + .lock = .init(), .nice = 0, .priority = Thread.Priority.default, .priority_class = Thread.Priority.Class.Batch,