diff --git a/core/src/arch/cpu.zig b/core/src/arch/cpu.zig index 694d49a..100cd80 100644 --- a/core/src/arch/cpu.zig +++ b/core/src/arch/cpu.zig @@ -28,11 +28,10 @@ pub fn setupCore(allocator: *pmm.FrameAllocator) !void { idle_thread.mapper = null; idle_thread.regs = std.mem.zeroes(@TypeOf(idle_thread.regs)); idle_thread.state = .Running; + idle_thread.user_priority = 0; thread.arch.initKernelRegisters(&idle_thread.regs); thread.arch.setAddress(&idle_thread.regs, @intFromPtr(&thread.arch.idleLoop)); - core.thread_list.append(&core.idle_thread); - const stack = try pmm.allocFrame(allocator); thread.arch.setStack(&idle_thread.regs, stack.virtualAddress(vmm.PHYSICAL_MAPPING_BASE) + (platform.PAGE_SIZE - 16)); diff --git a/core/src/main.zig b/core/src/main.zig index a33b1fa..dcc3df5 100644 --- a/core/src/main.zig +++ b/core/src/main.zig @@ -69,6 +69,7 @@ export fn _start(magic: u32, info: MultibootInfo) callconv(.C) noreturn { }; init.mapper = mapper; + init.user_priority = 255; thread.arch.initUserRegisters(&init.regs); thread.arch.setArgument(&init.regs, base); diff --git a/core/src/sys/sched.zig b/core/src/sys/sched.zig index 793f0ee..3587af9 100644 --- a/core/src/sys/sched.zig +++ b/core/src/sys/sched.zig @@ -1,7 +1,21 @@ const interrupts = @import("../arch/interrupts.zig").arch; const sys = @import("syscall.zig"); const thread = @import("../thread.zig"); +const cpu = @import("../arch/cpu.zig"); pub fn yield(regs: *interrupts.InterruptStackFrame, _: *sys.Arguments, _: *isize) anyerror!void { - thread.scheduleNewTask(regs); + const core = cpu.thisCore(); + const new_thread = thread.fetchNewTask(core, false) orelse return; + const current_thread = thread.scheduleNewTask(core, regs, new_thread); + thread.addThreadToPriorityQueue(core, current_thread); +} + +pub fn setPriority(_: *interrupts.InterruptStackFrame, args: *sys.Arguments, _: *isize) anyerror!void { + const core = cpu.thisCore(); + core.current_thread.user_priority = @truncate(args.arg0); +} + +pub fn getPriority(_: *interrupts.InterruptStackFrame, _: *sys.Arguments, retval: *isize) anyerror!void { + const core = cpu.thisCore(); + retval.* = core.current_thread.user_priority; } diff --git a/core/src/sys/syscall.zig b/core/src/sys/syscall.zig index 8a2232d..663e1d3 100644 --- a/core/src/sys/syscall.zig +++ b/core/src/sys/syscall.zig @@ -15,7 +15,7 @@ pub const Arguments = struct { const SystemCall = *const fn (frame: *interrupts.InterruptStackFrame, args: *Arguments, retval: *isize) anyerror!void; -const syscalls = [_]SystemCall{ print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield }; +const syscalls = [_]SystemCall{ print, mem.allocFrame, mem.lockFrame, mem.freeFrame, sched.yield, sched.setPriority, sched.getPriority }; pub fn invokeSyscall(number: usize, frame: *interrupts.InterruptStackFrame, args: *Arguments, retval: *isize) void { if (number >= syscalls.len) { diff --git a/core/src/thread.zig b/core/src/thread.zig index 49d7bfe..10b4862 100644 --- a/core/src/thread.zig +++ b/core/src/thread.zig @@ -18,6 +18,9 @@ pub const ThreadControlBlock = struct { state: ThreadState, ticks: u64, + + user_priority: u8, + current_priority: u32, }; pub const ThreadList = std.DoublyLinkedList(ThreadControlBlock); @@ -53,28 +56,47 @@ pub fn switchTask(regs: *interrupts.InterruptStackFrame, new_task: *ThreadContro core.current_thread = new_task; } -pub fn scheduleNewTask(regs: *interrupts.InterruptStackFrame) void { - const core = cpu.thisCore(); +pub fn fetchNewTask(core: *cpu.arch.Core, should_idle_if_not_found: bool) ?*ThreadControlBlock { + const last = core.thread_list.last orelse { + if (should_idle_if_not_found) { + return &core.idle_thread; + } else return null; + }; - const new_task = core.thread_list.popFirst() orelse return; - core.thread_list.append(new_task); + const new_task = &last.data; - switchTask(regs, &new_task.data); + removeThreadFromPriorityQueue(core, new_task); + + return new_task; +} + +pub fn scheduleNewTask(core: *cpu.arch.Core, regs: *interrupts.InterruptStackFrame, new_thread: *ThreadControlBlock) *ThreadControlBlock { + if (core.thread_list.first) |first| { + first.data.current_priority +|= 4; + } + + const current_thread = core.current_thread; + + switchTask(regs, new_thread); + + return current_thread; } pub fn preempt(regs: *interrupts.InterruptStackFrame) void { const core = cpu.thisCore(); - core.current_thread.ticks -= 1; + core.current_thread.ticks -|= 1; if (core.current_thread.ticks == 0) { - scheduleNewTask(regs); + const new_thread = fetchNewTask(core, false) orelse return; + const current_thread = scheduleNewTask(core, regs, new_thread); + addThreadToPriorityQueue(core, current_thread); } } var next_id: std.atomic.Value(u64) = std.atomic.Value(u64).init(1); pub fn addThreadToScheduler(core: *cpu.arch.Core, thread: *ThreadControlBlock) void { - core.thread_list.append(@fieldParentPtr("data", thread)); + addThreadToPriorityQueue(core, thread); } pub fn createThreadControlBlock(allocator: *pmm.FrameAllocator) !*ThreadControlBlock { @@ -86,6 +108,33 @@ pub fn createThreadControlBlock(allocator: *pmm.FrameAllocator) !*ThreadControlB thread.mapper = null; thread.regs = std.mem.zeroes(@TypeOf(thread.regs)); thread.state = .Inactive; + thread.user_priority = 0; return thread; } + +pub fn addThreadToPriorityQueue(core: *cpu.arch.Core, thread: *ThreadControlBlock) void { + thread.current_priority = thread.user_priority; + + var it: ?*ThreadList.Node = core.thread_list.first; + while (it) |n| : (it = n.next) { + if (thread.current_priority <= n.data.current_priority) { + n.data.current_priority -|= thread.current_priority; + core.thread_list.insertBefore(n, @fieldParentPtr("data", thread)); + return; + } + thread.current_priority -|= n.data.current_priority; + } + + core.thread_list.append(@fieldParentPtr("data", thread)); +} + +pub fn removeThreadFromPriorityQueue(core: *cpu.arch.Core, thread: *ThreadControlBlock) void { + const node: *ThreadList.Node = @fieldParentPtr("data", thread); + + if (node.next) |n| { + n.data.current_priority +|= thread.current_priority; + } + + core.thread_list.remove(node); +} diff --git a/system/init/kernel.zig b/system/init/kernel.zig index 22643b9..6e90838 100644 --- a/system/init/kernel.zig +++ b/system/init/kernel.zig @@ -4,6 +4,8 @@ const SystemCall = enum(u64) { LockFrame, FreeFrame, Yield, + SetPriority, + GetPriority, }; const SystemError = error{ @@ -39,3 +41,11 @@ pub fn freeFrame(address: u64) void { pub fn yield() void { _ = syscall(.Yield, 0); } + +pub fn setPriority(priority: u8) void { + _ = syscall(.SetPriority, priority); +} + +pub fn getPriority() u8 { + return @truncate(@as(u64, @bitCast(syscall(.GetPriority, 0)))); +} diff --git a/system/init/main.zig b/system/init/main.zig index 8525bc8..ed52b48 100644 --- a/system/init/main.zig +++ b/system/init/main.zig @@ -2,6 +2,10 @@ const kernel = @import("kernel.zig"); export fn _start(base: u64) callconv(.C) noreturn { kernel.print(base); + kernel.print(kernel.getPriority()); + + kernel.setPriority(128); + kernel.print(kernel.getPriority()); while (true) { kernel.yield();