// SPDX-FileCopyrightText: 2024 Himbeer // // SPDX-License-Identifier: AGPL-3.0-or-later const std = @import("std"); const interrupts = @import("interrupts.zig"); const paging = @import("paging.zig"); const num_stack_pages = 2; var next_pid = 1; var previous_scheduled = 1; var list = std.mem.zeroInit(std.DoublyLinkedList(Info)); pub const State = enum { waiting, active, sleeping, terminated, }; pub const Info = extern struct { id: u32, trap_frame: interrupts.TrapFrame, stack: [*]u8, pc: usize, page_table: *paging.Table, state: State, pub fn destroy(self: *Info) !void { try paging.free(self.stack); try self.page_table.unmap(); try paging.free(self.page_table); } }; fn new(entry: *fn () void) !Info { const stack = try paging.alloc(num_stack_pages); errdefer paging.free(stack); const procmem = try paging.zeroedAlloc(1); errdefer paging.free(procmem); const proc = .{ .id = next_pid, .trap_frame = std.mem.zeroInit(interrupts.TrapFrame), .stack = stack, .pc = @ptrCast(entry), .page_table = procmem, .state = .waiting, }; const stack_top = proc.stack + num_stack_pages * paging.page_size; proc.trap_frame.general_purpose_registers[2] = stack_top; try procmem.map(@intFromPtr(entry), @intFromPtr(entry), paging.EntryFlags.userReadExec, 0); // Not using identityMapRange because this is going to be expanded for non-relocatable binaries. for (0..num_stack_pages) |page| { const vaddr = page * paging.page_size; const paddr = page * paging.page_size; try procmem.map(vaddr, paddr, paging.EntryFlags.userReadWrite, 0); } next_pid += 1; return proc; } pub fn nextScheduled() ?Info { if (list.popFirst()) |next| { list.append(next); return next.data; } return null; }