diff options
| author | hachem <im@hachem.wtf> | 2026-10-04 03:05:36 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-10-04 03:05:36 +0200 |
| commit | 5cb9c6c03270487ee65a36828098f4f25f874bb6 (patch) | |
| tree | fcd4cb432faad25fbc8152ba4ee680fbc1af8bb1 /boot | |
| parent | 7c1bd03a71cccfcf48e79d241787021b0de98e73 (diff) | |
chore: cleanup
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/elf.zig | 2 | ||||
| -rw-r--r-- | boot/regs.zig | 6 | ||||
| -rw-r--r-- | boot/sched.zig | 33 |
3 files changed, 8 insertions, 33 deletions
diff --git a/boot/elf.zig b/boot/elf.zig index 906e380..51dc107 100644 --- a/boot/elf.zig +++ b/boot/elf.zig @@ -1,6 +1,4 @@ -// the embedded ring 3 programs, boot copies each to frames at startup pub const Program = struct { name: []const u8, bytes: []const u8 }; - pub const programs = [_]Program{ .{ .name = "hexview", .bytes = @embedFile("user_hexview") }, .{ .name = "calc", .bytes = @embedFile("user_calc") }, diff --git a/boot/regs.zig b/boot/regs.zig index aedae99..7b2bb88 100644 --- a/boot/regs.zig +++ b/boot/regs.zig @@ -24,10 +24,8 @@ pub const Frame = extern struct { ss: u64, }; -// push/pop the 15 gprs in frames exact order (rax pushed first -> highest field, -// r15 last -> at rsp = &frame). shared by every save/restore stub so they cant -// drift from the frame layout above. `mov %rsp, %rdi` after push_gprs hands the -// handler a *frame +// push/pop the 15 gprs in frames exact order +// (rax pushed first -> highest field, r15 last -> at rsp = &frame) pub const PUSH_GPRS = \\push %rax \\push %rbx diff --git a/boot/sched.zig b/boot/sched.zig index 60a8fa0..0857abe 100644 --- a/boot/sched.zig +++ b/boot/sched.zig @@ -26,18 +26,15 @@ var tasks: [MAX_TASKS]Task = @splat(.{}); var kstacks: [MAX_TASKS][KSTACK_SIZE]u8 align(16) = undefined; var current: usize = 0; var spawn_count: u64 = 0; -// the one task currently blocked in read(), if any var blocked_reader: ?usize = null; -// the "foreground" task that owns keyboard input (set when a task first reads, -// cleared when it exits). keystrokes route to it, into stdin_buf when it isnt -// currently blocked, so nothing is lost between its reads. else the shell + var foreground: ?usize = null; var stdin_buf: [64]u8 = undefined; var stdin_head: usize = 0; var stdin_tail: usize = 0; fn stdinPush(byte: u8) void { - if (stdin_tail -% stdin_head >= stdin_buf.len) return; // full, drop + if (stdin_tail -% stdin_head >= stdin_buf.len) return; stdin_buf[stdin_tail % stdin_buf.len] = byte; stdin_tail +%= 1; } @@ -54,9 +51,6 @@ pub fn init(kernel_cr3: u64) void { current = 0; } -// queue a ring 3 process. it starts running the next time the scheduler picks -// it (the tick copies its initial frame onto the stack and iretqs in). rdi is -// seeded with a small per spawn id so demo programs can tell instances apart pub fn spawn(cr3: u64, entry: u64, ustack: u64) void { var i: usize = 1; while (i < MAX_TASKS) : (i += 1) { @@ -79,7 +73,6 @@ pub fn spawn(cr3: u64, entry: u64, ustack: u64) void { } } -// number of live user processes (ready or blocked), excluding the kernel task pub fn procCount() u64 { var count: u64 = 0; var i: usize = 1; @@ -91,8 +84,7 @@ pub fn procCount() u64 { var proc_exited_flag: bool = false; -// mark the running process dead. it then sti+hlts, the next tick reclaims the -// slot and switches away, never returning here +// mark the running process dead. it then sti+hlts pub fn exitCurrent() void { if (current != 0) { tasks[current].state = .dead; @@ -105,23 +97,17 @@ pub fn exitCurrent() void { } } -// did a process exit since last checked? (consumed once.) pub fn takeProcExited() bool { const e = proc_exited_flag; proc_exited_flag = false; return e; } -// called at the top of read(): the caller becomes the foreground reader. returns -// a buffered byte if one is waiting (so read() neednt block), else null pub fn readReady() ?u8 { foreground = current; return stdinPop(); } -// block the running task in read(). `resume_frame` is a context that iretqs -// straight back to just after the processs int 0x80, so when input arrives we -// set its rax and mark it ready, and the scheduler resumes it there pub fn blockCurrentOnRead(resume_frame: Frame) void { if (current == 0) return; // the kernel task never blocks like this tasks[current].frame = resume_frame; @@ -129,9 +115,6 @@ pub fn blockCurrentOnRead(resume_frame: Frame) void { blocked_reader = current; } -// route one input byte. if a task is blocked in read(), wake it with the byte -// else if a foreground reader exists, buffer it for its next read(). returns -// false only when nothing wants it (so the caller feeds the shell instead) pub fn deliverInput(byte: u8) bool { if (blocked_reader) |task| { tasks[task].frame.rax = byte; // read()s return value @@ -146,20 +129,17 @@ pub fn deliverInput(byte: u8) bool { return false; } -// the preemption point, called from the pit irq with the interrupted frame pub fn tick(frame: *Frame) void { - // dont preempt task 0 mid vm call, the shared fiber cant be re-entered if (bridge.vmBusy()) return; if (tasks[current].state == .dead) { tasks[current].state = .free; // reclaim, dont bother saving its context } else if (tasks[current].state == .blocked) { - // keep the resume frame saved by blockcurrentonread, dont clobber it + // keep the resume frame saved by blockcurrentonread, dont clobber it you bitch } else { tasks[current].frame = frame.*; // freeze the current task } - // round robin to the next ready task var next = current; var i = current; var n: usize = 0; @@ -170,10 +150,9 @@ pub fn tick(frame: *Frame) void { break; } } - // if the current task cant continue (dead/blocked) and nothing else is - // ready, fall back to the kernel task (0), which is always ready + if (tasks[current].state != .ready and next == current) next = 0; - if (next == current) return; // nothing else to run, keep going + if (next == current) return; current = next; frame.* = tasks[current].frame; |
