Step 2: schedule()

This commit is contained in:
Jack Halford 2019-12-14 23:42:28 +01:00
parent 6af31b5b89
commit ec7ee599a1
5 changed files with 86 additions and 56 deletions

View file

@ -1,15 +1,13 @@
usingnamespace @import("index.zig"); usingnamespace @import("index.zig");
// shitty ring buffer, fight me.
var input_ring_buffer: [1024]u8 = [_]u8{0} ** 1024;
var input_read_index: u10 = 0;
var input_write_index: u10 = 0;
var command: [10]u8 = undefined; var command: [10]u8 = undefined;
var command_len: usize = 0; var command_len: usize = 0;
fn test_a() void {
var a: u32 = 2;
a += 1;
a = 4;
a -= 1;
}
fn execute(input: []u8) void { fn execute(input: []u8) void {
const eql = std.mem.eql; const eql = std.mem.eql;
if (eql(u8, input, "x86paging")) return x86.paging.introspect(); if (eql(u8, input, "x86paging")) return x86.paging.introspect();
@ -18,10 +16,6 @@ fn execute(input: []u8) void {
if (eql(u8, input, "lspci")) return pci.lspci(); if (eql(u8, input, "lspci")) return pci.lspci();
if (eql(u8, input, "uptime")) return time.uptime(); if (eql(u8, input, "uptime")) return time.uptime();
if (eql(u8, input, "topbar")) return topbar(); if (eql(u8, input, "topbar")) return topbar();
if (eql(u8, input, "test")) {
const tbar = task.Task.new(@ptrToInt(topbar)) catch unreachable;
while (true) tbar.switch_to();
}
println("{}: command not found", input); println("{}: command not found", input);
} }
@ -52,7 +46,19 @@ pub fn keypress(char: u8) void {
} }
} }
pub fn initialize() void { pub fn buffer_write(char: u8) void {
ps2.keyboard_callback = keypress; input_ring_buffer[input_write_index] = char;
print("> "); input_write_index +%= 1;
}
pub fn loop() void {
ps2.keyboard_callback = buffer_write;
print("> ");
while (true) {
if (input_write_index - input_read_index > 0) {
keypress(input_ring_buffer[input_read_index]);
input_read_index +%= 1;
}
task.schedule();
}
} }

View file

@ -25,8 +25,10 @@ export fn kmain(magic: u32, info: *const multiboot.MultibootInfo) noreturn {
vmem.initialize(); vmem.initialize();
pci.scan(); pci.scan();
console.initialize(); task.new(@ptrToInt(topbar)) catch unreachable;
// while (true) asm volatile ("hlt"); // task.new(@ptrToInt(console.loop)) catch unreachable;
const tbar = task.Task.new(@ptrToInt(topbar)) catch unreachable;
while (true) tbar.switch_to(); // task.schedule();
console.loop();
while (true) asm volatile ("hlt");
} }

View file

@ -1,8 +1,14 @@
pub usingnamespace @import("index.zig"); pub usingnamespace @import("index.zig");
const TASK_MAX = 1024;
var boot_task = Task{ .tid = 0, .esp = 0x47 }; var boot_task = Task{ .tid = 0, .esp = 0x47 };
var current_task: *Task = &boot_task; const ListOfTasks = std.TailQueue(*Task);
pub var tasks = [1]?*Task{&boot_task} ++ ([1]?*Task{null} ** TASK_MAX); var first_task = ListOfTasks.Node.init(&boot_task);
var current_task = &first_task;
var tasks = ListOfTasks{
.first = &first_task,
.last = &first_task,
.len = 1,
};
const STACK_SIZE = x86.PAGE_SIZE; // Size of thread stacks. const STACK_SIZE = x86.PAGE_SIZE; // Size of thread stacks.
var tid_counter: u16 = 1; var tid_counter: u16 = 1;
@ -16,9 +22,9 @@ pub const Task = packed struct {
//context: isr.Context, //context: isr.Context,
//cr3: usize, //cr3: usize,
pub fn new(entrypoint: usize) !*Task { pub fn create(entrypoint: usize) !*Task {
// Allocate and initialize the thread structure. // Allocate and initialize the thread structure.
var t = try vmem.allocate(Task); var t = try vmem.create(Task);
t.tid = tid_counter; t.tid = tid_counter;
tid_counter +%= 1; tid_counter +%= 1;
@ -33,46 +39,62 @@ pub const Task = packed struct {
t.esp -= 4; t.esp -= 4;
@intToPtr(*usize, t.esp).* = t.esp + 8; @intToPtr(*usize, t.esp).* = t.esp + 8;
println("new task esp=0x{x}, eip=0x{x}", t.esp, entrypoint);
tasks[t.tid] = t;
return t; return t;
} }
pub fn destroy(self: *Task) void { pub fn destroy(self: *Task) void {
tasks[self.tid] = null;
vmem.free(self.esp); vmem.free(self.esp);
vmem.free(@ptrToInt(self)); vmem.free(@ptrToInt(self));
} }
pub fn switch_to(self: *Task) void {
assert(self != current_task);
// save old stack
const old_task_esp_addr = &current_task.esp;
current_task = self;
// x86.cli();
// don't inline the asm function, it needs to ret
@noInlineCall(switch_tasks, self.esp, @ptrToInt(old_task_esp_addr));
// comptime {
// asm (
// \\mov +8(%esp), %eax
// \\mov %esp, (%eax)
// \\mov +4(%esp), %eax
// \\mov %eax, %esp
// \\pop %ebp
// \\ret
// );
// }
// x86.sti();
println("after switch");
}
}; };
pub fn new(entrypoint: usize) !void {
// println("currently: {}", current_task.data.tid);
// println("first: {}", tasks.first.?.data.tid);
// println("last: {}", tasks.last.?.data.tid);
const node = try vmem.create(ListOfTasks.Node);
node.data = try Task.create(entrypoint);
tasks.append(node);
// println("currently: {}", current_task.data.tid);
// println("first: {}", tasks.first.?.data.tid);
// println("last: {}", tasks.last.?.data.tid);
}
pub fn switch_to(new_task: *ListOfTasks.Node) void {
assert(new_task.data != current_task.data);
// save old stack
const old_task_esp_addr = &current_task.data.esp;
current_task = new_task;
// x86.cli();
// don't inline the asm function, it needs to ret
@noInlineCall(switch_tasks, new_task.data.esp, @ptrToInt(old_task_esp_addr));
// x86.sti();
}
pub fn schedule() void {
// println("currently: {}", current_task.data.tid);
// println("first: {}", tasks.first.?.data.tid);
// println("last: {}", tasks.last.?.data.tid);
if (current_task.next) |next| {
// println("switching to {}", next.data.tid);
switch_to(next);
} else if (tasks.first) |head| {
// println("switching to {}", head.data.tid);
if (head.data != current_task.data) switch_to(head);
} else {
introspect();
}
// if (current_task.data.tid == 0) switch_to(tasks.last.?.*);
// if (current_task.data.tid == 1) switch_to(tasks.first.?.*);
// if (current_task.tid == 2) tasks[0].?.switch_to();
}
pub fn introspect() void { pub fn introspect() void {
for (tasks) |t| { var it = tasks.first;
if (t == null) continue; println("{} tasks", tasks.len);
if (t != current_task) println("{}", t); while (it) |node| : (it = node.next) {
if (t == current_task) println("*{}", t); if (node.data != current_task.data) println("{}", node.data);
if (node.data == current_task.data) println("*{}", node.data);
} }
} }

View file

@ -63,9 +63,9 @@ pub fn clear() void {
vga.clear(); vga.clear();
} }
pub fn topbar() void { pub fn topbar() void {
const cursor = vga.cursor;
const bg = vga.background; const bg = vga.background;
while (true) { while (true) {
const cursor = vga.cursor;
vga.cursor = 0; vga.cursor = 0;
vga.background = Color.Red; vga.background = Color.Red;
@ -73,7 +73,7 @@ pub fn topbar() void {
vga.cursor = cursor; vga.cursor = cursor;
vga.background = bg; vga.background = bg;
task.tasks[0].?.switch_to(); task.schedule();
} }
} }

View file

@ -22,7 +22,7 @@ pub fn malloc(size: usize) !usize {
return vaddr; return vaddr;
} }
pub fn allocate(comptime T: type) !*T { pub fn create(comptime T: type) !*T {
assert(@sizeOf(T) < x86.PAGE_SIZE); // this allocator only support 1:1 mapping assert(@sizeOf(T) < x86.PAGE_SIZE); // this allocator only support 1:1 mapping
return @intToPtr(*T, try malloc(@sizeOf(T))); return @intToPtr(*T, try malloc(@sizeOf(T)));
} }