Skip to content

Commit

Permalink
Finish event.zig and other stuff
Browse files Browse the repository at this point in the history
Fix time.zig.
Remove fd.zig (merged with new_vfs.zig).
Add Stat, timespec and other types to lib/ubik.zig.
Add time to log and dmesg.
Start keyboardHandler for tty.
  • Loading branch information
Ratakor committed Nov 5, 2023
1 parent caad79d commit 442aa86
Show file tree
Hide file tree
Showing 15 changed files with 267 additions and 244 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ A kernel
Make sure to have `zig master`, `xorriso` and `qemu-system-x86` then run

```console
% git clone https://github.com/ratakor/ubik --recursive
% git clone git@github.com:ratakor/ubik --recursive
% zig build run -Doptimize=ReleaseFast
```

Expand Down
3 changes: 2 additions & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ fn buildImage(b: *std.Build, image_name: []const u8) *std.Build.Step.Run {
"--efi-boot limine-uefi-cd.bin ",
"-efi-boot-part --efi-boot-image --protective-msdos-label ",
image_dir, " -o ", image_name, " && ",
"./limine/limine bios-install ", image_name,
"./limine/limine bios-install ", image_name, " && ",
"rm -rf ", image_dir,
})
};

Expand Down
2 changes: 0 additions & 2 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@
},
},
.paths = .{
"kernel",
"lib",
"build.zig",
"build.zig.zon",
"LICENSE",
"limine.cfg",
"README.md",
},
}
24 changes: 18 additions & 6 deletions kernel/TTY.zig
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ g_select: u8,
charsets: [2]u8,
current_charset: usize,
escape_offset: usize,
esc_values_i: usize,
esc_values_i: usize, // TODO: ArrayList
esc_values: [MAX_ESC_VALUES]u32,
current_primary: usize,
current_bg: usize,
Expand All @@ -48,7 +48,7 @@ height: usize,

grid: []Char,
queue: []QueueItem,
queue_i: usize,
queue_i: usize, // TODO: ArrayList
map: []?*QueueItem,

text_fg: Color,
Expand Down Expand Up @@ -1659,6 +1659,18 @@ fn putChar(self: *Context, c: u8) void {
}
}

// TODO: unfinished + doesn't work well yet + should be somewhere else
pub fn keyboardHandler(self: *Context) noreturn {
const ev = @import("event.zig");
const ps2 = @import("ps2.zig");

while (true) {
var events = [_]*ev.Event{&ev.int_events[ps2.keyboard_vector]};
_ = ev.awaitEvents(events[0..], true);
self.readKey(ps2.read());
}
}

// TODO: tell kernel to grab input instead of doing it like that
// also do the things instead of using term.zig
pub fn readKey(self: *Context, input: u8) void {
Expand Down Expand Up @@ -1689,19 +1701,19 @@ pub fn readKey(self: *Context, input: u8) void {
},
// TODO for arrows we could also output A, B, C or D depending on termios settings
.arrow_up => {
root.os.system.term.cursorUp(self.writer(), 1) catch unreachable;
root.term.cursorUp(self.writer(), 1) catch unreachable;
return;
},
.arrow_left => {
root.os.system.term.cursorBackward(self.writer(), 1) catch unreachable;
root.term.cursorBackward(self.writer(), 1) catch unreachable;
return;
},
.arrow_down => {
root.os.system.term.cursorDown(self.writer(), 1) catch unreachable;
root.term.cursorDown(self.writer(), 1) catch unreachable;
return;
},
.arrow_right => {
root.os.system.term.cursorForward(self.writer(), 1) catch unreachable;
root.term.cursorForward(self.writer(), 1) catch unreachable;
return;
},
.insert, .home, .end, .pgup, .pgdown, .delete => return,
Expand Down
7 changes: 4 additions & 3 deletions kernel/arch/x86_64/idt.zig
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const IDTEntry = extern struct {
}
};

const IDTRegister = extern struct {
const IDTDescriptor = extern struct {
limit: u16 align(1) = @sizeOf(@TypeOf(idt)) - 1,
base: u64 align(1) = undefined,
};
Expand Down Expand Up @@ -103,7 +103,7 @@ var isr = [_]InterruptHandler{defaultHandler} ** 256;
var next_vector: u8 = exceptions.len;
pub var panic_ipi_vector: u8 = undefined;

var idtr: IDTRegister = .{};
var idtr: IDTDescriptor = .{};
var idt: [256]IDTEntry = undefined;

pub fn init() void {
Expand Down Expand Up @@ -134,7 +134,8 @@ pub fn reload() void {

pub fn allocVector() u8 {
const vector = @atomicRmw(u8, &next_vector, .Add, 1, .AcqRel);
if (vector >= 256 - 16) { // TODO - 16 ? also u8 so care about overflows
// 0xf0 in a non maskable interrupt from APIC
if (vector == 0xf0) {
@panic("IDT exhausted");
}
return vector;
Expand Down
18 changes: 16 additions & 2 deletions kernel/debug.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const root = @import("root");
const arch = @import("arch.zig");
const serial = @import("serial.zig");
const smp = @import("smp.zig");
const time = @import("time.zig");
const SpinLock = root.SpinLock;
const StackIterator = std.debug.StackIterator;

Expand Down Expand Up @@ -69,8 +70,21 @@ pub fn log(
log_lock.lock();
defer log_lock.unlock();

if (comptime scope != .gpa) dmesg_writer.print(fmt, args) catch {};
if (comptime builtin.mode == .Debug) serial.print(fmt, args);
if (comptime scope != .gpa) {
dmesg_writer.print("[{d: >5}.{d:0>6}] ", .{
@as(usize, @intCast(time.monotonic.tv_sec)),
@as(usize, @intCast(time.monotonic.tv_nsec)) / std.time.ns_per_ms,
}) catch {};
dmesg_writer.print(fmt, args) catch {};
}

if (comptime builtin.mode == .Debug) {
serial.print("[{d: >5}.{d:0>6}] ", .{
@as(usize, @intCast(time.monotonic.tv_sec)),
@as(usize, @intCast(time.monotonic.tv_nsec)) / std.time.ns_per_ms,
});
serial.print(fmt, args);
}
}

fn printStackIterator(writer: anytype, stack_iter: StackIterator) void {
Expand Down
167 changes: 83 additions & 84 deletions kernel/event.zig
Original file line number Diff line number Diff line change
@@ -1,138 +1,137 @@
const std = @import("std");
const root = @import("root");
const arch = @import("arch.zig");
const Thread = @import("sched.zig").Thread;
const SpinLock = @import("root").SpinLock;

// TODO: this is really ugly, also need threads to work
// TODO: using i as variable is ugly, use slices

pub const max_events = 32;
pub const max_listeners = 32;
const sched = @import("sched.zig");
const SpinLock = root.SpinLock;

pub const Listener = struct {
thread: *Thread,
thread: *sched.Thread,
which: usize,
};

pub const Event = struct {
lock: SpinLock = .{},
pending: usize = 0,
listeners_i: usize = 0,
listeners: [max_listeners]Listener,
lock: SpinLock,
pending: usize,
listeners: std.ArrayListUnmanaged(Listener),

pub const max_listeners = 32;

pub fn init() !Event {
return .{
.lock = .{},
.pending = 0,
.listeners = try std.ArrayListUnmanaged(Listener).initCapacity(root.allocator, max_listeners),
};
}

pub fn deinit(self: *Event) void {
self.listeners.deinit(root.allocator);
}

pub fn trigger(self: *Event, drop: bool) void {
const old_state = arch.toggleInterrupts(false);
defer _ = arch.toggleInterrupts(old_state);

self.lock.lock();
defer self.lock.unlock();

if (self.listeners.items.len == 0) {
if (!drop) {
self.pending += 1;
}
} else {
for (self.listeners.items) |listener| {
const thread = listener.thread;
thread.which_event = listener.which;
sched.enqueue(thread) catch unreachable;
}

self.listeners.clearRetainingCapacity();
}
}
};

pub var int_events: [256]Event = undefined;

pub fn init() void {
// TODO: init events handler like isr
for (32..0xef) |vec| {
arch.idt.registerHandler(@intCast(vec), intEventHandler);
int_events[vec] = Event.init() catch unreachable;
}
}

pub fn awaitEvent(events: []*Event, block: bool) isize {
// const thread = sched.currentThread;
pub fn awaitEvents(events: []*Event, block: bool) isize {
const thread = sched.currentThread();

const old_state = arch.toggleInterrupts(false);
defer _ = arch.toggleInterrupts(old_state);

// const old_ints = arch.toggleInterrupts(false);
// defer _ = arch.toggleInterrupts(old_ints);
lockEvents(events);
defer unlockEvents(events);

var i = checkForPending(events);
const i = checkForPending(events);
if (i != -1) return i;
if (!block) return -1;

attachListeners(events);
// thread.dequeue();
attachListeners(events, thread);
sched.dequeue(thread);
unlockEvents(events);
// sched.yield(true);
sched.yield(true);

// _ = arch.toggleInterrupts(false);
arch.disableInterrupts();

// const ret = if (thread.enqueued_by_signal) -1 else thread.which_event;
const ret = thread.which_event;

lockEvents(events);
// detachListeners(thread);
detachListeners(thread);

// return ret;
return @intCast(ret);
}

pub fn trigger(event: Event, drop: bool) usize {
const old_state = arch.toggleInterrupts(false);
defer _ = arch.toggleInterrupts(old_state);

event.lock.lock();
defer event.lock.unlock();

if (event.listeners_i == 0) {
if (!drop) {
event.pending += 1;
}
return 0;
}

for (0..event.listeners_i) |i| {
const listener = &event.listeners[i];
const thread = listener.thread;

thread.which_event = listener.which;
// sched.enqueueThread(thread, false);
}

const ret = event.listeners_i;
event.listeners_i = 0;
return ret;
fn intEventHandler(ctx: *arch.Context) callconv(.SysV) void {
int_events[ctx.vector].trigger(false);
arch.apic.eoi();
}

fn checkForPending(events: []*Event) isize {
for (events, 0..) |*event, i| {
for (events, 0..) |event, i| {
if (event.pending > 0) {
event.pending -= 1;
return i;
return @intCast(i);
}
}
return -1;
}

fn attachListeners(events: []*Event, thread: *Thread) void {
thread.attached_events_i = 0;
fn attachListeners(events: []*Event, thread: *sched.Thread) void {
thread.attached_events.clearRetainingCapacity();

for (events, 0..) |*event, i| {
if (event.listeners_i == max_listeners) {
@panic("Event listeners exhausted");
}

const listener = event.listeners[event.listeners_i];
event.listeners_i += 1;
listener.thread = thread;
listener.which = i;

if (thread.attached_events_i == max_events) {
@panic("Listening on too many events");
}

thread.attached_events[thread.attached_events_i] = event;
thread.attached_events_i += 1;
for (events, 0..) |event, i| {
event.listeners.appendAssumeCapacity(.{ .thread = thread, .which = i });
thread.attached_events.appendAssumeCapacity(event);
}
}

fn detachListeners(thread: *Thread) void {
for (0..thread.attached_events_i) |i| {
const event = thread.attached_events[i];

for (0..event.listeners_i) |j| {
const listener = &event.listeners[j];
if (listener.thread != thread) continue;

event.listeners_i -= 1;
event.listeners[j] = event.listeners[event.listeners_i];
break;
fn detachListeners(thread: *sched.Thread) void {
for (thread.attached_events.items) |event| {
for (event.listeners.items, 0..) |listener, i| {
if (listener.thread == thread) {
_ = event.listeners.swapRemove(i); // TODO: weird (loop)
}
}
}
thread.attached_events_i = 0;

thread.attached_events.clearRetainingCapacity();
}

fn lockEvents(events: []*Event) void {
inline fn lockEvents(events: []*Event) void {
for (events) |event| {
event.lock.lock();
}
}

fn unlockEvents(events: []*Event) void {
inline fn unlockEvents(events: []*Event) void {
for (events) |event| {
event.lock.unlock();
}
Expand Down
6 changes: 2 additions & 4 deletions kernel/fs/tmpfs.zig
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ const fs_vtable: vfs.FileSystem.VTable = .{

const File = struct {
vnode: vfs.VNode,
data: Data = Data.init(root.allocator),

const Data = std.ArrayListAligned(u8, page_size);
data: std.ArrayListAlignedUnmanaged(u8, page_size) = .{},

fn read(vnode: *vfs.VNode, buf: []u8, offset: usize, flags: usize) vfs.ReadError!usize {
_ = flags;
Expand All @@ -45,7 +43,7 @@ const File = struct {
_ = flags;

const self = @fieldParentPtr(File, "vnode", vnode);
try self.data.insertSlice(offset, buf);
try self.data.insertSlice(root.allocator, offset, buf);
return buf.len;
}

Expand Down
Loading

0 comments on commit 442aa86

Please sign in to comment.