Step 2: schedule()
This commit is contained in:
parent
6af31b5b89
commit
ec7ee599a1
5 changed files with 86 additions and 56 deletions
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
src/main.zig
10
src/main.zig
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
92
src/task.zig
92
src/task.zig
|
|
@ -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 = ¤t_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 = ¤t_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue