mirror of
https://github.com/rdmsr/zag.git
synced 2026-10-27 13:58:20 +00:00
ke: scheduler overhaul
This commit is contained in:
+1
-1
@@ -125,7 +125,7 @@ pub fn init() void {
|
||||
console_list.init();
|
||||
|
||||
const td = ps.thread.create_kernel(
|
||||
ke.Thread.Priority.default,
|
||||
.Default,
|
||||
worker,
|
||||
null,
|
||||
) catch @panic("handle me");
|
||||
|
||||
+2
-2
@@ -26,7 +26,7 @@ pub fn init() void {
|
||||
if (rtl.cmdline.get_string(cline, "test")) |tst| {
|
||||
// Run a test if specified.
|
||||
if (r.tests.tests.get(tst)) |func| {
|
||||
const t = ps.thread.create_kernel(ke.Thread.Priority.default, func, r.boot_info) catch @panic("oom");
|
||||
const t = ps.thread.create_kernel(.Default, func, r.boot_info) catch @panic("oom");
|
||||
ke.sched.enqueue(&t.kern);
|
||||
} else {
|
||||
std.log.info("invalid test: \"{s}\"", .{tst});
|
||||
@@ -35,6 +35,6 @@ pub fn init() void {
|
||||
}
|
||||
|
||||
if (r.boot_info.framebuffer != null) {
|
||||
// fbconsole.init(boot_info);
|
||||
// fbconsole.init(r.boot_info);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-5
@@ -50,11 +50,11 @@ pub const WorkItem = struct {
|
||||
/// High priority work.
|
||||
High,
|
||||
|
||||
pub fn to_sched_prio(prio: Priority) u8 {
|
||||
pub fn to_sched_prio(prio: Priority) ke.Thread.Priority {
|
||||
return switch (prio) {
|
||||
.Low => ke.Thread.Priority.low_batch,
|
||||
.Normal => ke.Thread.Priority.high_batch,
|
||||
.High => ke.Thread.Priority.low_realtime,
|
||||
.Low => .LowBatch,
|
||||
.Normal => .HighBatch,
|
||||
.High => .LowRealtime,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -128,6 +128,8 @@ const Pool = struct {
|
||||
@ptrFromInt(ctx.value),
|
||||
);
|
||||
|
||||
td.kern.nice = -ke.Thread.Priority.nice_max;
|
||||
|
||||
if (cpu != null) {
|
||||
td.kern.last_cpu = cpu;
|
||||
td.kern.pinned = true;
|
||||
@@ -312,7 +314,7 @@ pub fn init() !void {
|
||||
try low.init(.Low, null);
|
||||
|
||||
var td = ps.thread.create_kernel(
|
||||
ke.Thread.Priority.default,
|
||||
.Default,
|
||||
pool_manager,
|
||||
null,
|
||||
) catch @panic("Failed to create pool manager");
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ export fn kmain(boot_info: *r.BootInfo) callconv(.c) void {
|
||||
thread0.init(
|
||||
boot_info.kernel_stack,
|
||||
boot_info.kernel_stack_size,
|
||||
ke.Thread.Priority.idle_low,
|
||||
.IdleThread,
|
||||
init,
|
||||
null,
|
||||
);
|
||||
|
||||
+825
-666
File diff suppressed because it is too large
Load Diff
+50
-48
@@ -7,41 +7,55 @@ const ki = ke.private;
|
||||
|
||||
/// Structure representing a kernel thread.
|
||||
pub const Thread = struct {
|
||||
/// Thread priority classes.
|
||||
/// Realtime: Highest priority, aggressively scheduled.
|
||||
/// Batch: Normal priority.
|
||||
/// Idle: For idle and background threads.
|
||||
pub const Priority = struct {
|
||||
pub const Priority = enum(u8) {
|
||||
const Self = @This();
|
||||
|
||||
/// Reserved for the idle thread.
|
||||
IdleThread = 0,
|
||||
/// Background kernel work.
|
||||
Idle = 1,
|
||||
/// Low priority CPU-bound work
|
||||
LowBatch = 2,
|
||||
/// High priority CPU-bound work
|
||||
HighBatch = 137,
|
||||
/// Low priority interactive work.
|
||||
LowInteractive = 138,
|
||||
/// High priority interactive work.
|
||||
HighInteractive = 223,
|
||||
/// The default thread priority.
|
||||
Default = 117,
|
||||
/// Low priority real-time work.
|
||||
LowRealtime = 224,
|
||||
/// Mid priority real-time work.
|
||||
MidRealtime = 239,
|
||||
/// High priority real-time work.
|
||||
HighRealtime = 255,
|
||||
_,
|
||||
|
||||
pub const Class = enum(u8) {
|
||||
Realtime,
|
||||
Batch,
|
||||
Timeshare,
|
||||
Idle,
|
||||
};
|
||||
|
||||
/// Idle thread has the lowest priority.
|
||||
pub const idle_low = 0;
|
||||
pub const idle = 1;
|
||||
pub const max = 255;
|
||||
pub const nice_max = 20;
|
||||
|
||||
/// Batch threads have priorities 2-23
|
||||
pub const low_batch = 2;
|
||||
pub const high_batch = 23;
|
||||
pub const batch_range = high_batch - low_batch + 1;
|
||||
|
||||
/// Realtime threads have priorities 40-63
|
||||
pub const low_realtime = 40;
|
||||
pub const max = 63;
|
||||
|
||||
/// In the mid-range of batch threads
|
||||
pub const default = 10;
|
||||
|
||||
/// Interactive threads have priorities 24-39
|
||||
pub const low_interactive = 24;
|
||||
pub const high_interactive = 39;
|
||||
// The low and top 20 priorities from the batch range are reserved
|
||||
// for nice.
|
||||
pub const cpu_range = @intFromEnum(Self.HighBatch) - (nice_max * 2) - 1;
|
||||
|
||||
pub fn class_from_prio(prio: u8) Class {
|
||||
if (prio >= low_realtime and prio <= max) return .Realtime;
|
||||
if (prio >= low_batch and prio < low_realtime) return .Batch;
|
||||
if (prio <= idle) return .Idle;
|
||||
if (prio >= @intFromEnum(Self.LowRealtime) and
|
||||
prio <= @intFromEnum(Self.HighRealtime))
|
||||
return .Realtime;
|
||||
|
||||
if (prio >= @intFromEnum(Self.LowBatch) and
|
||||
prio < @intFromEnum(Self.LowRealtime))
|
||||
return .Timeshare;
|
||||
|
||||
if (prio <= @intFromEnum(Self.Idle))
|
||||
return .Idle;
|
||||
|
||||
unreachable;
|
||||
}
|
||||
@@ -74,12 +88,6 @@ pub const Thread = struct {
|
||||
base_priority: u8,
|
||||
/// Priority inherited via priority donation.
|
||||
inherited_prio: u8,
|
||||
/// When the thread started sleeping.
|
||||
sleep_start: u64,
|
||||
/// Ticks spent voluntarily sleeping recently.
|
||||
sleep_time: u64,
|
||||
/// Ticks spent running recently.
|
||||
run_time: u64,
|
||||
/// Whether the thread is pinned to this CPU.
|
||||
/// If it is pinned, then it can't be moved across another CPU.
|
||||
pinned: bool,
|
||||
@@ -116,6 +124,8 @@ pub const Thread = struct {
|
||||
stack: r.VAddr,
|
||||
/// PELT load average,
|
||||
avg: ki.sched.Average,
|
||||
/// Accounting statistics.
|
||||
acct: ki.sched.Accounting,
|
||||
/// Set whenever the thread is switching off its stack.
|
||||
/// This is used to avoid taking thread next lock to wait for switch off
|
||||
/// to complete.
|
||||
@@ -132,7 +142,7 @@ pub const Thread = struct {
|
||||
thread: *Thread,
|
||||
stack: r.VAddr,
|
||||
stack_size: usize,
|
||||
prio: u8,
|
||||
prio: Priority,
|
||||
entry: *const fn (?*anyopaque) void,
|
||||
arg: ?*anyopaque,
|
||||
) void {
|
||||
@@ -145,12 +155,9 @@ pub const Thread = struct {
|
||||
),
|
||||
.lock = .init(),
|
||||
.nice = 0,
|
||||
.priority = prio,
|
||||
.base_priority = prio,
|
||||
.priority = @intFromEnum(prio),
|
||||
.base_priority = @intFromEnum(prio),
|
||||
.inherited_prio = 0,
|
||||
.sleep_start = 0,
|
||||
.sleep_time = 0,
|
||||
.run_time = 0,
|
||||
.pinned = false,
|
||||
.state = .init(.Ready),
|
||||
.runq_link = .{},
|
||||
@@ -170,14 +177,8 @@ pub const Thread = struct {
|
||||
.queue_item = null,
|
||||
.stack = stack,
|
||||
.switching = .init(false),
|
||||
.avg = .{
|
||||
.last_update = .init(0),
|
||||
// New threads are considered heavy until they prove themselves,
|
||||
// this might allow for better balancing during bursts.
|
||||
.load = ki.sched.pelt_load_avg_max,
|
||||
.est = ki.sched.pelt_load_avg_max,
|
||||
.period_contrib = 0,
|
||||
},
|
||||
.avg = .{},
|
||||
.acct = .{},
|
||||
.smr_sections = undefined,
|
||||
};
|
||||
|
||||
@@ -201,7 +202,8 @@ pub const Thread = struct {
|
||||
}
|
||||
|
||||
pub fn is_interactive(self: *Thread) bool {
|
||||
return self.priority >= Priority.low_interactive and self.priority <= Priority.high_interactive;
|
||||
return self.priority >= @intFromEnum(Priority.LowInteractive) and
|
||||
self.priority <= @intFromEnum(Priority.HighInteractive);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ fn make_thread(
|
||||
const td = mm.zone.gpa.create(ke.Thread) catch
|
||||
@panic("Failed to allocate thread for AP");
|
||||
|
||||
td.init(stack, size, ke.Thread.Priority.idle_low, entrypoint, null);
|
||||
td.init(stack, size, .IdleThread, entrypoint, null);
|
||||
|
||||
td.pinned = true;
|
||||
return td;
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ pub fn init() void {
|
||||
/// - `entry`: entry point.
|
||||
/// - `arg`: argument passed to `entry`.
|
||||
pub fn create_kernel(
|
||||
prio: u8,
|
||||
prio: ke.Thread.Priority,
|
||||
entry: *const fn (arg: ?*anyopaque) void,
|
||||
arg: ?*anyopaque,
|
||||
) !*Thread {
|
||||
|
||||
@@ -154,12 +154,12 @@ fn particle(param: ?*anyopaque) void {
|
||||
}
|
||||
|
||||
fn spawn_particle(arg: ?*anyopaque) void {
|
||||
const t = ps.thread.create_kernel(ke.Thread.Priority.default, &particle, arg) catch @panic("OOM");
|
||||
const t = ps.thread.create_kernel(.Default, &particle, arg) catch @panic("OOM");
|
||||
ke.sched.enqueue(&t.kern);
|
||||
}
|
||||
|
||||
fn spawn_explodeable() void {
|
||||
const t = ps.thread.create_kernel(ke.Thread.Priority.default, &explodeable, null) catch @panic("OOM");
|
||||
const t = ps.thread.create_kernel(.Default, &explodeable, null) catch @panic("OOM");
|
||||
ke.sched.enqueue(&t.kern);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ pub fn start(_: ?*anyopaque) void {
|
||||
is_parked[i] = .init(false);
|
||||
|
||||
const prio: u8 = @intCast(2 + (i * 5) % 29);
|
||||
const t = ps.thread.create_kernel(prio, &worker, @ptrFromInt(i + 1)) catch @panic("oom");
|
||||
const t = ps.thread.create_kernel(@enumFromInt(prio), &worker, @ptrFromInt(i + 1)) catch @panic("oom");
|
||||
tds[i] = t;
|
||||
ke.sched.enqueue(&t.kern);
|
||||
}
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ fn poller(_: ?*anyopaque) void {
|
||||
}
|
||||
|
||||
fn spawn(entry: *const fn (?*anyopaque) void, id: usize) void {
|
||||
const t = ps.thread.create_kernel(ke.Thread.Priority.default, entry, @ptrFromInt(id + 1)) catch @panic("oom");
|
||||
const t = ps.thread.create_kernel(.Default, entry, @ptrFromInt(id + 1)) catch @panic("oom");
|
||||
ke.sched.enqueue(&t.kern);
|
||||
}
|
||||
|
||||
|
||||
@@ -279,7 +279,7 @@ fn quiesce_check() void {
|
||||
}
|
||||
|
||||
fn spawn(prio: u8, entry: *const fn (?*anyopaque) void, id: usize) *ps.Thread {
|
||||
const t = ps.thread.create_kernel(prio, entry, @ptrFromInt(id + 1)) catch @panic("oom");
|
||||
const t = ps.thread.create_kernel(@enumFromInt(prio), entry, @ptrFromInt(id + 1)) catch @panic("oom");
|
||||
ke.sched.enqueue(&t.kern);
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ fn chain_high(_: ?*anyopaque) void {
|
||||
}
|
||||
|
||||
fn spawn(prio: u8, entry: *const fn (?*anyopaque) void, arg: ?*anyopaque) *ps.Thread {
|
||||
const t = ps.thread.create_kernel(prio, entry, arg) catch @panic("oom");
|
||||
const t = ps.thread.create_kernel(@enumFromInt(prio), entry, arg) catch @panic("oom");
|
||||
ke.sched.enqueue(&t.kern);
|
||||
return t;
|
||||
}
|
||||
@@ -217,7 +217,7 @@ pub fn start(_: ?*anyopaque) void {
|
||||
const prio: u8 = @intCast(2 + (i * 5) % 29);
|
||||
stress_prio[i] = prio;
|
||||
|
||||
const t = ps.thread.create_kernel(prio, &stress, @ptrFromInt(i + 1)) catch @panic("oom");
|
||||
const t = ps.thread.create_kernel(@enumFromInt(prio), &stress, @ptrFromInt(i + 1)) catch @panic("oom");
|
||||
stress_tds[i] = t;
|
||||
ke.sched.enqueue(&t.kern);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user