ke: move priority out of thread

This commit is contained in:
Loïc Grégoire
2026-08-19 22:24:48 -04:00
parent 157179ea27
commit 0e48c47674
5 changed files with 67 additions and 66 deletions
+2 -2
View File
@@ -50,7 +50,7 @@ pub const WorkItem = struct {
/// High priority work. /// High priority work.
High, High,
pub fn to_sched_prio(prio: Priority) ke.Thread.Priority { pub fn to_sched_prio(prio: Priority) ke.Priority {
return switch (prio) { return switch (prio) {
.Low => .LowBatch, .Low => .LowBatch,
.Normal => .HighBatch, .Normal => .HighBatch,
@@ -128,7 +128,7 @@ const Pool = struct {
@ptrFromInt(ctx.value), @ptrFromInt(ctx.value),
); );
td.kern.nice = -ke.Thread.Priority.nice_max; td.kern.nice = -ke.Priority.nice_max;
if (cpu != null) { if (cpu != null) {
td.kern.last_cpu = cpu; td.kern.last_cpu = cpu;
+1
View File
@@ -21,6 +21,7 @@ pub const Queue = p.queue.Queue;
pub const Mutex = p.mutex.Mutex; pub const Mutex = p.mutex.Mutex;
pub const ShootdownState = p.shootdown.ShootdownState; pub const ShootdownState = p.shootdown.ShootdownState;
pub const Tunable = p.tunable.Tunable; pub const Tunable = p.tunable.Tunable;
pub const Priority = p.thread.Priority;
// === Exported Interfaces === // === Exported Interfaces ===
pub const panic = p.panic.panic; pub const panic = p.panic.panic;
+11 -11
View File
@@ -104,7 +104,7 @@ const pl = r.pl;
const runqueues_n = 64; const runqueues_n = 64;
const interactivity_threshold = 30; const interactivity_threshold = 30;
const scaling_factor = 50; const scaling_factor = 50;
const preempt_threshold = @intFromEnum(ke.Thread.Priority.LowRealtime); const preempt_threshold = @intFromEnum(ke.Priority.LowRealtime);
const balance_interval = @as(u64, config.sched_balance_interval); const balance_interval = @as(u64, config.sched_balance_interval);
const steal_threshold = 1; const steal_threshold = 1;
const pct_window_target = 10 * std.time.us_per_s; const pct_window_target = 10 * std.time.us_per_s;
@@ -536,7 +536,7 @@ fn recompute_priority(td: *ke.Thread) void {
// Choose a priority based on score, the lower the score, // Choose a priority based on score, the lower the score,
// the higher the priority it will be. // the higher the priority it will be.
// This is a simple formula I came up with that is probably good enough. // This is a simple formula I came up with that is probably good enough.
@intCast(@intFromEnum(ke.Thread.Priority.LowInteractive) + @intCast(@intFromEnum(ke.Priority.LowInteractive) +
((interactivity_threshold - score) / 2)) ((interactivity_threshold - score) / 2))
else blk: { else blk: {
// Thread is not interactive, compute priority from recent CPU usage. // Thread is not interactive, compute priority from recent CPU usage.
@@ -544,7 +544,7 @@ fn recompute_priority(td: *ke.Thread) void {
// thread has spent running, we want to punish threads that got to run // thread has spent running, we want to punish threads that got to run
// a lot and reward threads that got starved. // a lot and reward threads that got starved.
const len = @max(1, td.acct.stamp - td.acct.pct_window_start); const len = @max(1, td.acct.stamp - td.acct.pct_window_start);
const cpu_range = ke.Thread.Priority.cpu_range; const cpu_range = ke.Priority.cpu_range;
const cpu_pri_off: u8 = @intCast(@min( const cpu_pri_off: u8 = @intCast(@min(
cpu_range - 1, cpu_range - 1,
@@ -553,16 +553,16 @@ fn recompute_priority(td: *ke.Thread) void {
// nice offset: negative nice increases priority value, // nice offset: negative nice increases priority value,
// positive decreases it. // positive decreases it.
const nice_off: i16 = @as(i16, td.nice) + ke.Thread.Priority.nice_max; const nice_off: i16 = @as(i16, td.nice) + ke.Priority.nice_max;
const raw: i16 = @as(i16, @intFromEnum(ke.Thread.Priority.HighBatch)) - const raw: i16 = @as(i16, @intFromEnum(ke.Priority.HighBatch)) -
@as(i16, cpu_pri_off) - @as(i16, cpu_pri_off) -
nice_off; nice_off;
break :blk @intCast(std.math.clamp( break :blk @intCast(std.math.clamp(
raw, raw,
@intFromEnum(ke.Thread.Priority.LowBatch), @intFromEnum(ke.Priority.LowBatch),
@intFromEnum(ke.Thread.Priority.HighBatch), @intFromEnum(ke.Priority.HighBatch),
)); ));
}; };
@@ -593,7 +593,7 @@ fn pick_realtime_thread(cpu: *PerCpu, minimum_prio: u8, migrate: bool) ?*ke.Thre
if (runq.status == 0) return null; if (runq.status == 0) return null;
// Search higher priority queues first. // Search higher priority queues first.
var i: usize = to_sched_prio(ke.Thread.Priority.max); var i: usize = to_sched_prio(ke.Priority.max);
qloop: while (i >= minprio and i > 0) : (i -= 1) { qloop: while (i >= minprio and i > 0) : (i -= 1) {
const bit = (@as(u64, 1) << @intCast(i)); const bit = (@as(u64, 1) << @intCast(i));
@@ -754,7 +754,7 @@ fn insert_in_queue(cpu: *PerCpu, td: *ke.Thread, preempted: bool) void {
// Insert in calendar queue. // Insert in calendar queue.
// The insertion index is determined by insidx and the the priority of the thread, // The insertion index is determined by insidx and the the priority of the thread,
// higher priority threads will be put closer to insidx, which ensures that they are ran more frequently. // higher priority threads will be put closer to insidx, which ensures that they are ran more frequently.
var idx = (cpu.insidx + (@intFromEnum(ke.Thread.Priority.HighBatch) - var idx = (cpu.insidx + (@intFromEnum(ke.Priority.HighBatch) -
td.priority)) % runqueues_n; td.priority)) % runqueues_n;
if (preempted) { if (preempted) {
@@ -861,7 +861,7 @@ fn select_thread(cur: ?*ke.Thread, cpu: *PerCpu, migrate: bool) ?*ke.Thread {
// Return whether or not a thread with given priority and interactivity should // Return whether or not a thread with given priority and interactivity should
// get preempted by `td`. // get preempted by `td`.
fn should_prio_preempt(td: *ke.Thread, other_prio: u8, remote: bool) bool { fn should_prio_preempt(td: *ke.Thread, other_prio: u8, remote: bool) bool {
const class = ke.Thread.Priority.class_from_prio(other_prio); const class = ke.Priority.class_from_prio(other_prio);
if (td.priority <= other_prio) { if (td.priority <= other_prio) {
// If our priority is lower or equal, ignore. // If our priority is lower or equal, ignore.
@@ -874,7 +874,7 @@ fn should_prio_preempt(td: *ke.Thread, other_prio: u8, remote: bool) bool {
} }
if (class == .Timeshare and td.is_interactive() and if (class == .Timeshare and td.is_interactive() and
other_prio < @intFromEnum(ke.Thread.Priority.LowInteractive) and remote) other_prio < @intFromEnum(ke.Priority.LowInteractive) and remote)
{ {
// Interactive threads always preempt batch non-interactive ones // Interactive threads always preempt batch non-interactive ones
// on remote CPUs. // on remote CPUs.
+4 -4
View File
@@ -5,9 +5,7 @@ const rtl = @import("rtl");
const ke = r.ke; const ke = r.ke;
const ki = ke.private; const ki = ke.private;
/// Structure representing a kernel thread. pub const Priority = enum(u8) {
pub const Thread = struct {
pub const Priority = enum(u8) {
const Self = @This(); const Self = @This();
/// Reserved for the idle thread. /// Reserved for the idle thread.
@@ -59,8 +57,10 @@ pub const Thread = struct {
unreachable; unreachable;
} }
}; };
/// Structure representing a kernel thread.
pub const Thread = struct {
/// Thread state. /// Thread state.
pub const State = enum(u8) { pub const State = enum(u8) {
/// The thread is ready to run. /// The thread is ready to run.
+1 -1
View File
@@ -56,7 +56,7 @@ pub fn init() void {
/// - `entry`: entry point. /// - `entry`: entry point.
/// - `arg`: argument passed to `entry`. /// - `arg`: argument passed to `entry`.
pub fn create_kernel( pub fn create_kernel(
prio: ke.Thread.Priority, prio: ke.Priority,
entry: *const fn (arg: ?*anyopaque) void, entry: *const fn (arg: ?*anyopaque) void,
arg: ?*anyopaque, arg: ?*anyopaque,
) !*Thread { ) !*Thread {