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");
// 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 input_ring: Ring(u8) = undefined;
var command: [10]u8 = undefined;
var command_len: usize = 0;
@ -52,19 +49,17 @@ pub fn keypress(char: u8) void {
}
}
pub fn buffer_write(char: u8) void {
input_ring_buffer[input_write_index] = char;
input_write_index +%= 1;
pub fn keyboard_callback(char: u8) void {
input_ring.write(char);
}
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("> ");
while (true) {
if (input_write_index - input_read_index > 0) {
keypress(input_ring_buffer[input_read_index]);
input_read_index +%= 1;
}
// task.usleep(10 * 1000) catch unreachable;
while (input_ring.read()) |c| keypress(c);
task.block(.IOWait);
}
}

View file

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

View file

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

View file

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