sylveos

Toy Operating System
Log | Files | Refs

commit cb7d76930d24502ddd809028be54fdb6447b971c
parent 9a630c179e45cbf574f3613efce2f5d0c507031b
Author: Sylvia Ivory <git@sivory.net>
Date:   Sat, 24 Jan 2026 23:33:48 -0800

Use std.DoublyLinkedList for Scheduler

Diffstat:
Msrc/scheduler.zig | 62++++++++++++++++++++++++++++++--------------------------------
1 file changed, 30 insertions(+), 32 deletions(-)

diff --git a/src/scheduler.zig b/src/scheduler.zig @@ -3,16 +3,14 @@ const std = @import("std"); const Self = @This(); tid_counter: usize, -tasks_head: ?*Task, -tasks_tail: ?*Task, +tasks: std.DoublyLinkedList, scheduler_task: *Task, allocator: std.mem.Allocator, pub const Task = struct { tid: usize, - next: ?*Task, + node: std.DoublyLinkedList.Node, - // TODO; make generic(?) func: *const fn (*Self, ?*anyopaque) callconv(.c) void, arg: ?*anyopaque, @@ -27,7 +25,7 @@ pub const Task = struct { }; pub fn new(gpa: std.mem.Allocator) Self { - return .{ .tid_counter = 1, .tasks_head = null, .tasks_tail = null, .scheduler_task = undefined, .allocator = gpa }; + return .{ .tid_counter = 1, .tasks = .{}, .scheduler_task = undefined, .allocator = gpa }; } fn push_stack(sp: *usize, value: usize) *usize { @@ -44,7 +42,6 @@ pub fn fork(self: *Self, f: *const fn (*Self, ?*anyopaque) callconv(.c) void, ar task.func = f; task.arg = arg; - task.next = null; const stack_top = @intFromPtr(&task.stack) + task.stack.len; var sp: *usize = @ptrFromInt(stack_top); @@ -62,18 +59,15 @@ pub fn fork(self: *Self, f: *const fn (*Self, ?*anyopaque) callconv(.c) void, ar task.saved_sp = sp; - if (self.tasks_tail) |tail| { - tail.next = task; - } - self.tasks_tail = task; + self.tasks.append(&task.node); +} - if (self.tasks_head == null) { - self.tasks_head = task; - } +fn get_current(self: *Self) *Task { + return @alignCast(@fieldParentPtr("node", self.tasks.first.?)); } pub fn join(self: *Self) !void { - if (self.tasks_head == null) { + if (self.tasks.first == null) { // Nothing to do return; } @@ -82,40 +76,44 @@ pub fn join(self: *Self) !void { self.scheduler_task.tid = 0; self.scheduler_task.saved_sp = @ptrFromInt(@frameAddress()); - context_switch(&self.scheduler_task.saved_sp, self.tasks_head.?.saved_sp); + context_switch(&self.scheduler_task.saved_sp, self.get_current().saved_sp); } pub fn yield(self: *Self) void { - if (self.tasks_head == self.tasks_tail) { + // Single task + if (self.tasks.first == self.tasks.last) { return; } - const current = self.tasks_head.?; - self.tasks_head = current.next; - current.next = null; - self.tasks_tail.?.next = current; - self.tasks_tail = current; - - const next = self.tasks_head.?; + const node = self.tasks.popFirst().?; + self.tasks.append(node); + const current: *Task = @alignCast(@fieldParentPtr("node", node)); - context_switch(&current.saved_sp, next.saved_sp); + context_switch(&current.saved_sp, self.get_current().saved_sp); } pub fn get_tid(self: *Self) usize { - return self.tasks_head.?.tid; + return self.get_current().tid; } export fn trampoline_inner(self: *Self) callconv(.c) void { - const current = self.tasks_head.?; - current.func(self, current.arg); + { + const current: *Task = self.get_current(); + current.func(self, current.arg); + } + + // We aren't preserving sp as the function ended + const current: *Task = @alignCast(@fieldParentPtr("node", self.tasks.popFirst().?)); + var saved_sp = current.saved_sp; + // Free the task + self.allocator.destroy(current); - if (current.next) |next| { - self.tasks_head = next; + if (self.tasks.first) |node| { + const next: *Task = @alignCast(@fieldParentPtr("node", node)); + context_switch(&saved_sp, next.saved_sp); } else { - self.tasks_head = self.scheduler_task; + context_switch(&saved_sp, self.scheduler_task.saved_sp); } - - context_switch(&current.saved_sp, self.tasks_head.?.saved_sp); } comptime {