Skip to content

Commit

Permalink
Remove sched.wait() + add waiting_threads
Browse files Browse the repository at this point in the history
  • Loading branch information
Ratakor committed Nov 17, 2023
1 parent 30f468f commit 57e2404
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 47 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ A kernel
- Add a checklist/roadmap
- Move tty and drivers out of kernel space
- Replace json with zon
- Replace ArrayList(Unmanaged) with HashMap where needed
- Replace unreachable with @panic
- Provide compatibility with Linux ABI
- Support RISC-V64, aarch64 and x86_64
- Replace @import("root") with @import("main.zig") to allow for testing
- Replace limine with a custom bootloader?

# Clone, build and run
Expand Down
23 changes: 11 additions & 12 deletions kernel/arch/x86_64/idt.zig
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const IDTDescriptor = extern struct {
base: u64 align(1) = undefined,
};

const exceptions = [_]?[]const u8{
const exceptions = [_][]const u8{
"Division by zero",
"Debug",
"Non-maskable Interrupt",
Expand All @@ -80,23 +80,23 @@ const exceptions = [_]?[]const u8{
"Stack-Segment Fault",
"General Protection Fault",
"Page Fault",
null,
"Reserved",
"x87 Floating-Point Exception",
"Alignment Check",
"Machine Check",
"SIMD Floating-Point Exception",
"Virtualization Exception",
"Control Protection Exception",
null,
null,
null,
null,
null,
null,
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Reserved",
"Hypervisor Injection Exception",
"VMM Communication Exception",
"Security Exception",
null,
"Reserved",
};

// TODO: replace isr with a interrupt dispatcher func?
Expand Down Expand Up @@ -174,7 +174,7 @@ fn defaultHandler(ctx: *Context) callconv(.SysV) void {

const cr3 = x86.readRegister("cr3");
std.debug.panic(
\\Unhandled interruption "{?s}" triggered, dumping context
\\Unhandled interruption "{s}" triggered, dumping context
\\vector: 0x{x:0>2} error code: 0x{x}
\\ds: 0x{x:0>16} es: 0x{x:0>16}
\\rax: 0x{x:0>16} rbx: 0x{x:0>16}
Expand All @@ -189,7 +189,7 @@ fn defaultHandler(ctx: *Context) callconv(.SysV) void {
\\rsp: 0x{x:0>16} ss: 0x{x:0>16}
\\cr2: 0x{x:0>16} cr3: 0x{x:0>16}
, .{
if (ctx.vector < exceptions.len) exceptions[ctx.vector] else null,
if (ctx.vector < exceptions.len) exceptions[ctx.vector] else "Unknown",
ctx.vector,
ctx.error_code,
ctx.ds,
Expand Down Expand Up @@ -249,7 +249,6 @@ export fn commonStub() callconv(.Naked) void {
\\je 1f
\\swapgs
\\1:
\\cld
\\push %r15
\\push %r14
\\push %r13
Expand Down
2 changes: 2 additions & 0 deletions kernel/arch/x86_64/mem.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub fn cpy(noalias dst: ?[*]u8, noalias src: ?[*]const u8, len: usize) callconv(
@setRuntimeSafety(false);

asm volatile (
\\cld
\\rep movsb
:
: [_] "{rdi}" (dst),
Expand All @@ -17,6 +18,7 @@ pub fn set(dst: ?[*]u8, c: u8, len: usize) callconv(.C) ?[*]u8 {
@setRuntimeSafety(false);

asm volatile (
\\cld
\\rep stosb
:
: [_] "{rdi}" (dst),
Expand Down
6 changes: 3 additions & 3 deletions kernel/arch/x86_64/x86_64.zig
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub const MSR = enum(u32) {
kernel_gs_base = 0xc0000102,
};

pub const CPUID = struct {
pub const CpuID = struct {
eax: u32,
ebx: u32,
ecx: u32,
Expand Down Expand Up @@ -137,7 +137,7 @@ pub inline fn writeRegister(comptime reg: []const u8, value: u64) void {
);
}

pub inline fn cpuid(leaf: u32, subleaf: u32) CPUID {
pub inline fn cpuid(leaf: u32, subleaf: u32) CpuID {
var eax: u32 = undefined;
var ebx: u32 = undefined;
var ecx: u32 = undefined;
Expand All @@ -153,7 +153,7 @@ pub inline fn cpuid(leaf: u32, subleaf: u32) CPUID {
[_] "{ecx}" (subleaf),
);

return CPUID{ .eax = eax, .ebx = ebx, .ecx = ecx, .edx = edx };
return .{ .eax = eax, .ebx = ebx, .ecx = ecx, .edx = edx };
}

pub inline fn rdmsr(msr: MSR) u64 {
Expand Down
7 changes: 4 additions & 3 deletions kernel/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ pub const os = struct {
};

var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = false,
.MutexType = lib.SpinLock,
.verbose_log = if (builtin.mode == .Debug) true else false,
}){};
Expand Down Expand Up @@ -77,15 +76,17 @@ export fn _start() noreturn {
pmm.init();
vmm.init();
acpi.init();
event.init();
event.init(); // TODO + futex
// syscall.init(); // TODO
sched.init();
smp.init();
time.init();

const kernel_thread = sched.Thread.initKernel(@ptrCast(&main), null, 1) catch unreachable;
sched.enqueue(kernel_thread) catch unreachable;
sched.wait();

arch.enableInterrupts();
arch.halt();
}

fn main() noreturn {
Expand Down
2 changes: 1 addition & 1 deletion kernel/mm/pmm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub fn init() void {
const entries = memory_map.entries();
var highest_addr: u64 = 0;

log.info("memory_map[{}] dump:", .{entries.len});
log.info("memory_map[{}]:", .{entries.len});
for (entries) |entry| {
log.info("0x{x}-0x{x} {s}", .{
entry.base,
Expand Down
19 changes: 11 additions & 8 deletions kernel/mm/vmm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const MAP = std.os.MAP;

// TODO: mapRange/unmapRange?
// TODO: move paging code to paging.zig
// TODO: use ArenaAllocator for vmm

pub const MapError = error{
OutOfMemory,
Expand Down Expand Up @@ -89,7 +90,7 @@ pub const PageFaultError = packed struct(u32) {
// TODO: init and deinit func?
const MMapRangeGlobal = struct {
shadow_addr_space: *AddressSpace,
locals: std.ArrayListUnmanaged(*MMapRangeLocal) = .{},
locals: std.ArrayListUnmanaged(*MMapRangeLocal) = .{}, // HashMap?
// resource: *Resource, // TODO: vnode?
base: usize,
length: usize,
Expand Down Expand Up @@ -137,7 +138,7 @@ const Addr2Range = struct {
pub const AddressSpace = struct {
pml4: *[512]PTE,
lock: SpinLock = .{},
mmap_ranges: std.ArrayListUnmanaged(*MMapRangeLocal) = .{},
mmap_ranges: std.ArrayListUnmanaged(*MMapRangeLocal) = .{}, // HashMap?

pub fn init() !*AddressSpace {
const addr_space = try root.allocator.create(AddressSpace);
Expand Down Expand Up @@ -310,10 +311,11 @@ pub const AddressSpace = struct {

// TODO: lock?
fn flush(self: *AddressSpace, vaddr: u64) void {
std.debug.assert(arch.interruptState() == false);
// const old_state = arch.toggleInterrupts(false);
// defer _ = arch.toggleInterrupts(old_state);
// std.debug.assert(arch.interruptState() == false);
const old_state = arch.toggleInterrupts(false);
defer _ = arch.toggleInterrupts(old_state);

// TODO: is `if` useful?
if (self.cr3() == arch.readRegister("cr3")) {
arch.invlpg(vaddr);
}
Expand All @@ -338,10 +340,10 @@ pub const AddressSpace = struct {
prot: i32,
flags: i32,
) !void {
flags |= MAP.ANONYMOUS; // TODO
// flags |= MAP.ANONYMOUS; // TODO

const aligned_vaddr = alignBackward(vaddr, page_size);
const aligned_len = alignForward(len + (vaddr - aligned_vaddr), page_size);
const aligned_vaddr = alignBackward(u64, vaddr, page_size);
const aligned_len = alignForward(u64, len + (vaddr - aligned_vaddr), page_size);

const global_range = try root.allocator.create(MMapRangeGlobal);
errdefer root.allocator.destroy(global_range);
Expand Down Expand Up @@ -552,6 +554,7 @@ fn tlbShootdownHandler(ctx: *arch.Context) callconv(.SysV) void {
_ = ctx;

if (smp.thisCpu().tlb_shootdown_cr3 == arch.readRegister("cr3")) {
// TODO: invlpg cpu.tlb_Shootdown_addr?
arch.writeRegister("cr3", arch.readRegister("cr3"));
}

Expand Down
51 changes: 33 additions & 18 deletions kernel/sched.zig
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub const Process = struct {
child_events: std.ArrayListUnmanaged(*Event),
event: Event,
// running_time: usize, // TODO
// status: enum { running, ready, blocked (io) }, // TODO: in threads? + atomic (replace lock)
user: std.os.uid_t,
group: std.os.gid_t,

Expand Down Expand Up @@ -111,7 +112,6 @@ pub const Thread = struct {

// running_time: usize, // TODO

const Set = std.AutoArrayHashMapUnmanaged(*Thread, void);
pub const max_events = 32;
pub const stack_size = 8 * 1024 * 1024; // 8MiB
pub const stack_pages = stack_size / std.mem.page_size;
Expand Down Expand Up @@ -299,13 +299,12 @@ pub const Thread = struct {
};

/// reschedule every 5ms
pub const timeslice = 5_000;
/// wait for 10ms if there is no thread
pub const wait_timeslice = 10_000;
const quantum = 5_000;

pub var kernel_process: *Process = undefined;
pub var processes: std.ArrayListUnmanaged(*Process) = .{}; // TODO: hashmap with pid?
var running_threads: Thread.Set = .{};
var running_threads: std.AutoArrayHashMapUnmanaged(*Thread, void) = .{};
var waiting_threads: std.AutoArrayHashMapUnmanaged(*Thread, void) = .{};
var total_tickets: usize = 0;

var sched_vector: u8 = undefined;
Expand Down Expand Up @@ -365,6 +364,12 @@ pub fn enqueue(thread: *Thread) !void {

for (smp.cpus) |cpu| {
if (cpu.current_thread == null) {
// only for debug build
// fix to not crash when starting the first kernel thread
if (comptime @import("builtin").mode == .Debug) {
if (cpu.id == smp.thisCpu().id) continue;
}

apic.sendIPI(cpu.lapic_id, .{ .vector = sched_vector });
break;
}
Expand Down Expand Up @@ -401,7 +406,7 @@ fn schedHandler(ctx: *arch.Context) callconv(.SysV) void {

// if (cpu.scheduling_disabled) {
// apic.eoi();
// apic.timerOneShot(timeslice, sched_vector);
// apic.timerOneShot(quantum, sched_vector);
// return;
// }

Expand All @@ -412,7 +417,7 @@ fn schedHandler(ctx: *arch.Context) callconv(.SysV) void {

if (maybe_next_thread == null and current_thread.enqueued) {
apic.eoi();
apic.timerOneShot(timeslice, sched_vector);
apic.timerOneShot(quantum, sched_vector);
return;
}

Expand Down Expand Up @@ -449,22 +454,23 @@ fn schedHandler(ctx: *arch.Context) callconv(.SysV) void {
}

apic.eoi();
apic.timerOneShot(timeslice, sched_vector);
apic.timerOneShot(quantum, sched_vector);
contextSwitch(&next_thread.ctx);
} else {
cpu.current_thread = null;
vmm.switchPageTable(vmm.kaddr_space.cr3());
apic.eoi();
wait();
arch.halt();
}
unreachable;
}

pub fn wait() noreturn {
arch.disableInterrupts();
apic.timerOneShot(wait_timeslice, sched_vector);
arch.enableInterrupts();
arch.halt();
// TODO: wake is the same but reverse
fn blockThread(thread: *Thread) void {
dequeue(thread);
sched_lock.lock();
waiting_threads.putNoClobber(root.allocator, thread, {}) catch unreachable;
sched_lock.unlock();
}

pub fn yield() noreturn {
Expand All @@ -486,18 +492,27 @@ pub fn yieldAwait() void {
apic.timerStop();

const thread = currentThread();
thread.yield_await.lock();

const use_yield_await = false;
if (use_yield_await) {
thread.yield_await.lock();
} else {
blockThread();
}

apic.sendIPI(undefined, .{ .vector = sched_vector, .destination_shorthand = .self });
arch.enableInterrupts();

// TODO: useless since yield_await should already be unlocked
thread.yield_await.lock();
thread.yield_await.unlock();
if (use_yield_await) {
// TODO: useless since yield_await should already be unlocked
thread.yield_await.lock();
thread.yield_await.unlock();
}
}

fn contextSwitch(ctx: *arch.Context) noreturn {
std.debug.assert(ctx.cs == gdt.kernel_code);
// TODO: switch page table?
asm volatile (
\\mov %[ctx], %rsp
\\pop %rax
Expand Down
3 changes: 2 additions & 1 deletion kernel/smp.zig
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,6 @@ fn initAp(smp_info: *limine.SmpInfo) callconv(.C) noreturn {
log.info("processor {} is online", .{cpu_local.id});
_ = @atomicRmw(usize, &cpus_started, .Add, 1, .Release);

sched.wait();
arch.enableInterrupts();
arch.halt();
}
3 changes: 3 additions & 0 deletions lib/ubik.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const std = @import("std");
const linux = std.os.linux;

pub const PATH_MAX = 4096;
pub const STDIN_FILENO = 0;
pub const STDOUT_FILENO = 1;
pub const STDERR_FILENO = 2;

pub const T = linux.T;
pub const S = linux.S;
Expand Down

0 comments on commit 57e2404

Please sign in to comment.