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");
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
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];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
34
src/task.zig
34
src/task.zig
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue