ring buffer for the keyboard
This commit is contained in:
parent
c64c6cbcfe
commit
4148314d84
6 changed files with 64 additions and 28 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
31
src/ring_buffer.zig
Normal 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];
|
||||
}
|
||||
};
|
||||
}
|
||||
32
src/task.zig
32
src/task.zig
|
|
@ -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
|
||||
|
||||
// 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);
|
||||
unlock_scheduler();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn terminate() void {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue