ring buffer for the keyboard

This commit is contained in:
Jack Halford 2020-01-01 21:59:05 +01:00
parent c64c6cbcfe
commit 4148314d84
6 changed files with 64 additions and 28 deletions

View file

@ -1,9 +1,6 @@
usingnamespace @import("index.zig"); usingnamespace @import("index.zig");
// shitty ring buffer, fight me. var input_ring: Ring(u8) = undefined;
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;
@ -52,19 +49,17 @@ pub fn keypress(char: u8) void {
} }
} }
pub fn buffer_write(char: u8) void { pub fn keyboard_callback(char: u8) void {
input_ring_buffer[input_write_index] = char; input_ring.write(char);
input_write_index +%= 1;
} }
pub fn loop() void { pub fn loop() void {
ps2.keyboard_callback = buffer_write; input_ring.init() catch unreachable;
input_ring.task = task.current_task;
ps2.keyboard_callback = keyboard_callback;
print("> "); print("> ");
while (true) { while (true) {
if (input_write_index - input_read_index > 0) { while (input_ring.read()) |c| keypress(c);
keypress(input_ring_buffer[input_read_index]); task.block(.IOWait);
input_read_index +%= 1;
}
// task.usleep(10 * 1000) catch unreachable;
} }
} }

View file

@ -3,6 +3,7 @@ pub const builtin = @import("builtin");
pub const std = @import("std"); pub const std = @import("std");
pub const assert = std.debug.assert; pub const assert = std.debug.assert;
pub usingnamespace @import("delta_queue.zig"); pub usingnamespace @import("delta_queue.zig");
pub usingnamespace @import("ring_buffer.zig");
pub usingnamespace @import("vga.zig"); pub usingnamespace @import("vga.zig");
///arch ///arch

View file

@ -22,7 +22,7 @@ export fn kmain(magic: u32, info: *const multiboot.MultibootInfo) noreturn {
println("--- x86 initialization ---"); println("--- x86 initialization ---");
x86.x86_main(info); x86.x86_main(info);
println("--- core initialization ---"); println("--- core initialization ---");
vmem.initialize(); vmem.init();
pci.scan(); pci.scan();
task.cleaner_task = task.new(@ptrToInt(task.cleaner_loop)) catch unreachable; task.cleaner_task = task.new(@ptrToInt(task.cleaner_loop)) catch unreachable;

31
src/ring_buffer.zig Normal file
View file

@ -0,0 +1,31 @@
usingnamespace @import("index.zig");
pub fn Ring(comptime T: type) type {
return struct {
const Self = @This();
const Size = u10; // 0-1024
const size = @import("std").math.maxInt(Size);
buffer: *[size]T,
task: ?*task.TaskNode = null,
read_index: Size = 0,
write_index: Size = 0,
//TODO: allocator argument and remove the namespace
pub fn init(ring: *Self) !void {
ring.buffer = try vmem.create(@typeOf(ring.buffer.*));
}
pub fn write(ring: *Self, elem: T) void {
ring.buffer[ring.write_index] = elem;
ring.write_index +%= 1;
if (ring.task) |t| task.unblock(t);
}
pub fn read(ring: *Self) ?T {
if (ring.write_index == ring.read_index) return null;
const id = ring.read_index;
ring.read_index +%= 1;
return ring.buffer[id];
}
};
}

View file

@ -25,11 +25,12 @@ pub fn update_time_used() void {
} }
pub const TaskState = enum { pub const TaskState = enum {
Running, Running, // <=> current_task
ReadyToRun, ReadyToRun, // <=> inside of ready_tasks
Paused, IOWait, // waiting to be woken up by IO
Sleeping, Paused, // unpaused arbitrarily by another process
Terminated, Sleeping, // woken up by timer
Terminated, // <=> inside of terminated_tasks, waiting to be destroyed
}; };
pub const Task = struct { pub const Task = struct {
@ -124,6 +125,8 @@ pub fn block(state: TaskState) void {
assert(state != .Running); assert(state != .Running);
assert(state != .ReadyToRun); assert(state != .ReadyToRun);
// println("blocking {} as {}", current_task.data.tid, state);
lock_scheduler(); lock_scheduler();
defer unlock_scheduler(); defer unlock_scheduler();
@ -134,17 +137,22 @@ pub fn block(state: TaskState) void {
} }
pub fn unblock(node: *TaskNode) void { pub fn unblock(node: *TaskNode) void {
if (node.data.state != .Paused and node.data.state != .IOWait) return;
lock_scheduler(); lock_scheduler();
defer unlock_scheduler();
node.data.state = .ReadyToRun; node.data.state = .ReadyToRun;
blocked_tasks.remove(node); blocked_tasks.remove(node);
if (ready_tasks.first == null) {
// Only one task was running before, so pre-empt // TODO: find a way to fastpath here, hard because of unblock inside of interrupts
switch_to(node); // if (current_task.data.state != .Running and ready_tasks.first == null) {
} else { // // Only one task was running before, fastpath
// There's at least one task on the "ready to run" queue already, so don't pre-empt // switch_to(node);
ready_tasks.append(node); // } else {
unlock_scheduler(); // // There's at least one task on the "ready to run" queue already, so don't pre-empt
} // ready_tasks.append(node);
// }
ready_tasks.append(node);
} }
pub fn terminate() void { pub fn terminate() void {

View file

@ -1,4 +1,5 @@
pub usingnamespace @import("index.zig"); pub usingnamespace @import("index.zig");
pub const allocator: std.mem.Allocator = undefined;
// TODO: make a better memory allocator // TODO: make a better memory allocator
// stupid simple virtual memory allocator // stupid simple virtual memory allocator
@ -39,7 +40,7 @@ pub fn free(address: usize) void {
stack_index += 1; stack_index += 1;
} }
pub fn initialize() void { pub fn init() void {
var addr: usize = layout.HEAP; var addr: usize = layout.HEAP;
while (addr < layout.HEAP_END) : (addr += x86.PAGE_SIZE) { while (addr < layout.HEAP_END) : (addr += x86.PAGE_SIZE) {
// println("addr {x}", addr); // println("addr {x}", addr);