Skip to content

Commit

Permalink
multitasking!
Browse files Browse the repository at this point in the history
Signed-off-by: TalonFloof <[email protected]>
  • Loading branch information
TalonFloof committed Nov 17, 2024
1 parent c0fef4a commit 24ac3a7
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 8 deletions.
11 changes: 8 additions & 3 deletions kobold/hal/alarmqueue.zig
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const physmem = @import("root").physmem;
pub const AlarmQueueNode = struct {
deadline: u64,
data: ?*anyopaque = null,
func: *fn (?*anyopaque) callconv(.C) void,
func: *const fn (?*anyopaque) callconv(.C) void,
};

const AlarmQueueList = std.DoublyLinkedList(AlarmQueueNode);
Expand All @@ -22,22 +22,25 @@ pub const AlarmQueue = struct {
timerCounter: u64 = 0,
timerNextInterval: u64 = 0,

pub fn addAlarm(self: *AlarmQueue, timeout: u64, func: *fn (?*anyopaque) callconv(.C) void, data: ?*anyopaque) *AlarmQueueList.Node {
pub fn addAlarm(self: *AlarmQueue, timeout: u64, func: *const fn (?*anyopaque) callconv(.C) void, data: ?*anyopaque) *AlarmQueueList.Node {
const old = hal.arch.intControl(false);
self.lock.acquire();
const node: AlarmQueueList.Node = @ptrCast(@alignCast(physmem.Allocate(@sizeOf(AlarmQueueList.Node), @alignOf(AlarmQueueList.node)).?));
const node: *AlarmQueueList.Node = @ptrCast(@alignCast(physmem.Allocate(@sizeOf(AlarmQueueList.Node), @alignOf(AlarmQueueList.Node)).?));
node.data.deadline = self.timerCounter + timeout;
node.data.data = data;
node.data.func = func;
self.list.append(node);
self.schedule();
self.lock.release();
_ = hal.arch.intControl(old);
return node;
}

pub fn removeAlarm(self: *AlarmQueue, aqn: *AlarmQueueList.Node) void {
const old = hal.arch.intControl(false);
self.lock.acquire();
self.list.remove(aqn);
physmem.Free(@intFromPtr(aqn), @sizeOf(AlarmQueueList.Node));
self.schedule();
self.lock.release();
_ = hal.arch.intControl(old);
Expand All @@ -54,6 +57,8 @@ pub const AlarmQueue = struct {
i.data.func(i.data.data);
self.list.remove(i);
ind = next;
physmem.Free(@intFromPtr(i), @sizeOf(AlarmQueueList.Node));
continue;
} else if (i.data.deadline < closestDeadline) {
closestDeadline = i.data.deadline;
ind = i.next;
Expand Down
4 changes: 2 additions & 2 deletions kobold/hal/hal.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ pub export fn HALInitialize(stackTop: usize, dtb: *allowzero anyopaque) callconv
@panic("MMUless setups are not supported!");
team.Init();
thread.Init();
root.KoboldInit();
@panic("No Command");
_ = thread.NewThread(team.kteam.?, "Kobold Initialization Thread", @intFromPtr(&root.KoboldInit), null, 16);
root.StartMultitasking();
}

pub fn HALOops(s: []const u8) void {
Expand Down
2 changes: 2 additions & 0 deletions kobold/hal/hart.zig
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub const HartInfo = struct {
trapStack: usize = 0,
alarmQueue: alarmqueue.AlarmQueue = .{},
archData: ArchData = ArchData{},
activeThread: ?*anyopaque = null,
schedulePending: bool = false,
hartID: usize = 0,

comptime {
Expand Down
5 changes: 5 additions & 0 deletions kobold/hal/x86_64/isr.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const std = @import("std");
const hal = @import("../hal.zig");
const apic = @import("apic.zig");
const scheduler = @import("root").scheduler;

pub fn stub() void {}

Expand All @@ -19,6 +20,10 @@ pub export fn IRQHandler(entry: u8, con: *hal.arch.Context) callconv(.C) *hal.ar
queue.lock.acquire();
queue.schedule();
queue.lock.release();
if (hal.arch.getHart().schedulePending) {
hal.arch.getHart().schedulePending = false;
scheduler.Schedule(con);
}
}
return con;
}
23 changes: 22 additions & 1 deletion kobold/hal/x86_64/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const flanterm = @cImport({
@cInclude("backends/fb.h");
});

extern fn ContextEnter(context: *allowzero void) callconv(.C) noreturn;

pub export fn _start() callconv(.Naked) noreturn {
asm volatile (
\\mov %rsp, %rdi
Expand Down Expand Up @@ -303,9 +305,28 @@ const Context = packed struct {
std.log.debug(" rip 0x{x: <16} rsp 0x{x: <16} rflags 0x{x: <16}\n", .{ self.rip, self.rsp, self.rflags });
std.log.debug(" error code: 0x{x}\n", .{self.errcode});
}

pub inline fn Enter(self: *Context) noreturn {
ContextEnter(@as(*allowzero void, @ptrFromInt(@intFromPtr(self))));
}
};

const FloatContext = packed struct {};
const FloatContext = struct {
data: [512]u8 align(16) = [_]u8{0} ** 512,

pub fn Save(self: *FloatContext) void {
asm volatile ("fxsave64 (%rax)"
:
: [state] "{rax}" (&self.data),
);
}
pub fn Load(self: *FloatContext) void {
asm volatile ("fxrstor64 (%rax)"
:
: [state] "{rax}" (&self.data),
);
}
};

fn fthConvert(pte: usize, high: bool) hal.memmodel.HALPageFrame { // high set if not at 4 KiB granularity
const frame: hal.memmodel.HALPageFrame = .{};
Expand Down
1 change: 1 addition & 0 deletions kobold/hal/x86_64/timer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub fn init() void {
}
apic.write(0x3e0, 0xb);
apic.write(0x320, 0x20);
apic.write(0x380, 0);
}

pub fn setDeadline(microsecs: u64) void {
Expand Down
9 changes: 9 additions & 0 deletions kobold/kernel/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub const elf = @import("elf.zig");
pub const pfn = @import("pfn.zig");
pub const team = @import("team.zig");
pub const thread = @import("thread.zig");
pub const scheduler = @import("scheduler.zig");

pub const kmain_log = std.log.scoped(.KernelMain);

Expand Down Expand Up @@ -55,4 +56,12 @@ pub fn panic(msg: []const u8, stacktrace: ?*std.builtin.StackTrace, retAddr: ?us

pub export fn KoboldInit() void {
_ = hal.AlignDown(u32, 0, 4096); // Prevents release builds from failing
std.log.info("Schedling Started", .{});
while (true) {
hal.arch.waitForInt();
}
}

pub fn StartMultitasking() noreturn {
scheduler.Schedule(null);
}
63 changes: 62 additions & 1 deletion kobold/kernel/scheduler.zig
Original file line number Diff line number Diff line change
@@ -1,10 +1,71 @@
const std = @import("std");
const thread = @import("thread.zig");
const Spinlock = @import("spinlock.zig").Spinlock;
const Spinlock = @import("perlib").Spinlock;
const hal = @import("hal");

pub const Queue = struct {
lock: Spinlock = .unaquired,
queue: thread.ThreadList = .{},
};

pub var readyQueues: [64]Queue = [_]Queue{Queue{}} ** 64;

fn GetNextThread() *thread.Thread {
var i: usize = 63;
while (true) : (i -= 1) {
if (readyQueues[i].queue.first != null) {
readyQueues[i].lock.acquire();
if (readyQueues[i].queue.first != null) {
const t = readyQueues[i].queue.popFirst();
readyQueues[i].lock.release();
return t.?.data;
} else {
readyQueues[i].lock.release();
continue;
}
}
if (i == 0) {
hal.HALOops("No Available Threads in any of the Run Queues!");
unreachable;
}
}
}

fn rescheduleAlarm(data: ?*anyopaque) callconv(.C) void {
_ = data;
hal.arch.getHart().schedulePending = true;
}

pub fn Schedule(con: ?*hal.arch.Context) noreturn {
const hart = hal.arch.getHart();
if (hart.activeThread) |activeT| {
const activeThread: *thread.Thread = @alignCast(@ptrCast(activeT));
if (con) |c| {
activeThread.gpContext = c.*;
activeThread.fContext.Save();
}
if (activeThread.state == .Running) {
activeThread.state = .Runnable;
readyQueues[activeThread.priority].lock.acquire();
readyQueues[activeThread.priority].queue.append(&activeThread.queueNode);
readyQueues[activeThread.priority].lock.release();
}
}
var thr: *thread.Thread = GetNextThread();
while (true) {
if (thr.state == .Runnable) {
thr.state = .Running;
break;
} else {
readyQueues[thr.priority].lock.acquire();
readyQueues[thr.priority].queue.append(&thr.queueNode);
readyQueues[thr.priority].lock.release();
}
thr = GetNextThread();
}
hart.activeThread = @alignCast(@ptrCast(thr));
hart.activeSyscallStack = @intFromPtr(thr.kstack.ptr) + (thr.kstack.len - 8);
_ = hart.alarmQueue.addAlarm(10000, &rescheduleAlarm, null);
thr.fContext.Load();
thr.gpContext.Enter();
}
6 changes: 5 additions & 1 deletion kobold/kernel/thread.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Spinlock = @import("root").Spinlock;
const team = @import("team.zig");
const RedBlackTree = @import("perlib").RedBlackTree;
const physmem = @import("physmem.zig");
const scheduler = @import("scheduler.zig");

pub const ThreadState = enum {
Runnable,
Expand Down Expand Up @@ -41,7 +42,7 @@ pub var nextThreadID: i64 = 1;

pub fn NewThread(
t: *team.Team,
name: []u8,
name: []const u8,
ip: usize,
sp: ?usize,
prior: usize,
Expand Down Expand Up @@ -70,6 +71,9 @@ pub fn NewThread(
}
thread.gpContext.SetReg(128, ip);
t.threads.append(&thread.teamListNode);
scheduler.readyQueues[thread.priority].lock.acquire();
scheduler.readyQueues[thread.priority].queue.prepend(&thread.queueNode);
scheduler.readyQueues[thread.priority].lock.release();
threadLock.release();
_ = hal.arch.intControl(old);
return thread;
Expand Down

0 comments on commit 24ac3a7

Please sign in to comment.