aboutsummaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-07-01 23:30:51 +0200
committerHimbeer <himbeer@disroot.org>2024-07-01 23:30:51 +0200
commit64aab3ba1e8f6120f59e2923a8bbae02e16693d9 (patch)
tree7c35e93bba91e7d0fda5c74a16b70de09e02020e /src/lib
parentae2418ccaebdfcede0a79ce7b1e1e574ff468c72 (diff)
syscall: Implement opening resources
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/process.zig22
-rw-r--r--src/lib/syscall.zig33
-rw-r--r--src/lib/vfs.zig18
3 files changed, 60 insertions, 13 deletions
diff --git a/src/lib/process.zig b/src/lib/process.zig
index 0ab11ae..6f8ffce 100644
--- a/src/lib/process.zig
+++ b/src/lib/process.zig
@@ -9,6 +9,7 @@ const instructions = @import("instructions.zig");
const paging = @import("paging.zig");
const time = @import("sbi/time.zig");
const trap = @import("trap.zig");
+const vfs = @import("vfs.zig");
const elf = std.elf;
@@ -25,6 +26,10 @@ pub const Error = error{
NoInit,
};
+pub const ProcessError = error{
+ TooManyResourceDescriptors,
+};
+
pub const ExeError = error{
BadEndian,
BadArch,
@@ -42,23 +47,37 @@ pub const State = enum(u8) {
terminated,
};
-pub const Info = extern struct {
+pub const Info = struct {
id: u16,
trap_frame: trap.Frame,
stack: *[num_stack_pages * paging.page_size]u8,
pc: usize,
page_table: *paging.Table,
state: State,
+ rds: std.AutoArrayHashMap(usize, vfs.ResourceDescriptor),
pub fn destroy(self: *Info) !void {
try paging.free(self.stack);
try self.page_table.unmap();
try paging.free(self.page_table);
+ self.rds.deinit();
}
pub fn satp(self: *const Info) paging.Satp {
return self.page_table.satp(self.id);
}
+
+ pub fn makeRdHandle(self: *Info, rd: vfs.ResourceDescriptor) !usize {
+ if (self.rds.count() == std.math.maxInt(usize)) {
+ return ProcessError.TooManyResourceDescriptors;
+ }
+
+ var handle = self.rds.count() + 1;
+ while (self.rds.contains(handle)) : (handle +%= 1) {}
+
+ try self.rds.put(handle, rd);
+ return handle;
+ }
};
pub fn next() ?*Info {
@@ -195,6 +214,7 @@ pub fn create(allocator: std.mem.Allocator, elf_buf: []align(@alignOf(elf.Elf64_
.pc = hdr.entry,
.page_table = procmem,
.state = .waiting,
+ .rds = std.AutoArrayHashMap(usize, vfs.ResourceDescriptor).init(allocator),
};
proc.trap_frame.general_purpose_registers[2] = stack_top;
diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig
index eece736..c2457c6 100644
--- a/src/lib/syscall.zig
+++ b/src/lib/syscall.zig
@@ -4,6 +4,7 @@
const instructions = @import("instructions.zig");
const paging = @import("paging.zig");
+const process = @import("process.zig");
const sysexchange = @import("sysexchange.zig");
const trap = @import("trap.zig");
const vfs = @import("vfs.zig");
@@ -12,10 +13,10 @@ pub const Error = error{
UnknownSyscall,
};
-pub fn handle(trap_frame: *trap.Frame) !void {
+pub fn handle(proc: *process.Info, trap_frame: *trap.Frame) !void {
switch (trap_frame.general_purpose_registers[17]) {
100000 => uprint(trap_frame),
- 100001 => open(trap_frame),
+ 100001 => open(proc, trap_frame),
100002 => close(trap_frame),
100003 => provideStream(trap_frame),
100004 => provideFile(trap_frame),
@@ -40,12 +41,22 @@ fn uprint(trap_frame: *const trap.Frame) void {
w.print("User message: {s}\r\n", .{str}) catch unreachable;
}
-// open(path: [*:0]const u8) Result(usize) // fixme: Kernel panic if null pointer
-fn open(trap_frame: *const trap.Frame) void {
+// open(path: [*:0]const u8, data: usize) Result(usize) // fixme: Kernel panic if null pointer
+fn open(proc: *process.Info, trap_frame: *trap.Frame) void {
const path: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
-
- _ = path;
- unreachable;
+ const data = trap_frame.general_purpose_registers[11];
+
+ const user_info = vfs.openZ(path, proc.id, data) catch |err| {
+ sysexchange.frameReturn(usize, trap_frame, err);
+ return;
+ };
+ switch (user_info) {
+ .rd => |resource_descriptor| {
+ const maybe_handle = proc.makeRdHandle(resource_descriptor);
+ sysexchange.frameReturn(null, trap_frame, maybe_handle);
+ },
+ .value => |value| sysexchange.frameReturnResult(usize, trap_frame, value),
+ }
}
// close(rd: usize) void
@@ -66,7 +77,7 @@ fn provideStream(trap_frame: *trap.Frame) void {
const readFn: ?vfs.Stream.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[11]);
const writeFn: ?vfs.Stream.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[12]);
- sysexchange.frameReturn(trap_frame, vfs.provideResourceZ(path, .{
+ sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path, .{
.stream = .{
.readFn = readFn,
.writeFn = writeFn,
@@ -88,7 +99,7 @@ fn provideFile(trap_frame: *trap.Frame) void {
const writeFn: ?vfs.File.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[13]);
const closeFn: ?vfs.File.CloseFn = @ptrFromInt(trap_frame.general_purpose_registers[14]);
- sysexchange.frameReturn(trap_frame, vfs.provideResourceZ(path, .{
+ sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path, .{
.file = .{
.openFn = openFn,
.readFn = readFn,
@@ -106,7 +117,7 @@ fn provideHook(trap_frame: *trap.Frame) void {
const path: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
const callback: vfs.Hook.Callback = @ptrFromInt(trap_frame.general_purpose_registers[11]);
- sysexchange.frameReturn(trap_frame, vfs.provideResourceZ(path, .{
+ sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path, .{
.hook = .{
.callback = callback,
},
@@ -138,7 +149,7 @@ fn provideDirHook(trap_frame: *trap.Frame) void {
const findFn: vfs.DirHook.FindFn = @ptrFromInt(trap_frame.general_purpose_registers[12]);
const removeFn: vfs.DirHook.RemoveFn = @ptrFromInt(trap_frame.general_purpose_registers[13]);
- sysexchange.frameReturn(trap_frame, vfs.provideResourceZ(path, .{
+ sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path, .{
.dir_hook = .{
.provideFn = provideFn,
.findFn = findFn,
diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig
index 0eb57a6..56834d6 100644
--- a/src/lib/vfs.zig
+++ b/src/lib/vfs.zig
@@ -116,7 +116,6 @@ pub const Tree = struct {
pub const ResourceDescriptor = struct {
inode: *Inode,
- pos: usize = 0,
pub fn init(inode: *Inode) !ResourceDescriptor {
inode.refs = std.math.add(usize, inode.refs, 1) catch return Error.TooManyReferences;
@@ -130,6 +129,11 @@ pub const ResourceDescriptor = struct {
}
};
+pub const UserInfo = union(enum) {
+ rd: ResourceDescriptor,
+ value: sysexchange.Result(usize),
+};
+
pub fn init(allocator: mem.Allocator) void {
root = Tree.init(allocator);
}
@@ -174,3 +178,15 @@ pub fn provideResource(path: []const u8, resource: Resource) !void {
pub fn provideResourceZ(path_c: [*:0]const u8, resource: Resource) !void {
return provideResource(mem.sliceTo(path_c, 0), resource);
}
+
+pub fn open(path: []const u8, pid: u16, data: usize) !UserInfo {
+ const node = find(path) orelse return Error.NotFound;
+ return switch (node.data.resource) {
+ .hook => |hook| .{ .value = hook.callback(pid, data) },
+ else => .{ .rd = try ResourceDescriptor.init(&node.data) },
+ };
+}
+
+pub fn openZ(path_c: [*:0]const u8, pid: u16, data: usize) !UserInfo {
+ return open(mem.sliceTo(path_c, 0), pid, data);
+}