aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib/syscall.zig19
-rw-r--r--src/lib/vfs.zig79
2 files changed, 61 insertions, 37 deletions
diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig
index 419938f..ae86af1 100644
--- a/src/lib/syscall.zig
+++ b/src/lib/syscall.zig
@@ -60,17 +60,12 @@ fn open(proc: *process.Info, trap_frame: *trap.Frame) void {
const path_c: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
const data = trap_frame.general_purpose_registers[11];
- const user_info = vfs.openZ(path_c, proc.id, data) catch |err| {
+ const rd = vfs.openZ(proc, path_c, proc.id, data) catch |err| {
sysexchange.frameReturn(usize, trap_frame, err);
return;
};
- switch (user_info) {
- .rd => |resource_descriptor| {
- const maybe_handle = proc.createRdHandle(resource_descriptor);
- sysexchange.frameReturn(null, trap_frame, maybe_handle);
- },
- .value => |value| sysexchange.frameReturnResult(usize, trap_frame, value),
- }
+ const maybe_handle = proc.createRdHandle(rd);
+ sysexchange.frameReturn(null, trap_frame, maybe_handle);
}
// close(handle: usize) void
@@ -191,7 +186,7 @@ fn remove(trap_frame: *const trap.Frame) void {
}
// read(handle: usize, buffer: [*]u8, len: usize) Result(usize)
-fn read(proc: *const process.Info, trap_frame: *trap.Frame) void {
+fn read(proc: *process.Info, trap_frame: *trap.Frame) void {
setUserMemoryAccess(true);
defer setUserMemoryAccess(false);
@@ -203,11 +198,11 @@ fn read(proc: *const process.Info, trap_frame: *trap.Frame) void {
sysexchange.frameReturn(usize, trap_frame, process.Error.BadRdHandle);
return;
};
- sysexchange.frameReturnResult(usize, trap_frame, rd.read(buffer[0..len]));
+ sysexchange.frameReturn(usize, trap_frame, rd.read(proc, buffer[0..len]));
}
// write(handle: usize, bytes: [*]const u8, len: usize) Result(usize)
-fn write(proc: *const process.Info, trap_frame: *trap.Frame) void {
+fn write(proc: *process.Info, trap_frame: *trap.Frame) void {
setUserMemoryAccess(true);
defer setUserMemoryAccess(false);
@@ -219,7 +214,7 @@ fn write(proc: *const process.Info, trap_frame: *trap.Frame) void {
sysexchange.frameReturn(usize, trap_frame, process.Error.BadRdHandle);
return;
};
- sysexchange.frameReturnResult(usize, trap_frame, rd.write(bytes[0..len]));
+ sysexchange.frameReturn(usize, trap_frame, rd.write(proc, bytes[0..len]));
}
// terminate() noreturn
diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig
index ebd879f..22cba72 100644
--- a/src/lib/vfs.zig
+++ b/src/lib/vfs.zig
@@ -4,11 +4,12 @@
const std = @import("std");
+const process = @import("process.zig");
const sysexchange = @import("sysexchange.zig");
const mem = std.mem;
-var root: Node = .{ .data = .{ .name = "", .resource = .{ .dir = undefined } } };
+var root: Node = .{ .data = .{ .name = "", .resource = .{ .dir = undefined }, .pid = 0 } };
pub const Error = error{
NotFound,
@@ -77,6 +78,7 @@ pub const Inode = struct {
name: []const u8,
resource: Resource,
refs: usize = 0,
+ pid: u16,
};
pub const Node = std.DoublyLinkedList(Inode).Node;
@@ -130,29 +132,33 @@ pub const ResourceDescriptor = struct {
self.inode.refs -|= 1;
}
- pub fn read(self: ResourceDescriptor, buffer: []u8) sysexchange.Result(usize) {
- const err_unsupported = sysexchange.Result(usize).fromAnyTypeOrError(Error.ReadNotSupported);
-
+ pub fn read(self: ResourceDescriptor, proc: *process.Info, buffer: []u8) !noreturn {
return switch (self.inode.resource) {
- .stream => |stream| blk: {
- const readFn = stream.readFn orelse return err_unsupported;
- break :blk readFn(buffer);
+ .stream => |stream| {
+ const readFn = stream.readFn orelse return Error.ReadNotSupported;
+ proc.state = .suspended;
+ try call(self.inode.pid, readFn, .{buffer}, .{
+ .hookFn = crossProcessReturn,
+ .context = proc,
+ });
},
- .hook => err_unsupported,
- else => err_unsupported,
+ .hook => Error.ReadNotSupported,
+ else => Error.ReadNotSupported,
};
}
- pub fn write(self: ResourceDescriptor, bytes: []const u8) sysexchange.Result(usize) {
- const err_unsupported = sysexchange.Result(usize).fromAnyTypeOrError(Error.WriteNotSupported);
-
+ pub fn write(self: ResourceDescriptor, proc: *process.Info, bytes: []const u8) !noreturn {
return switch (self.inode.resource) {
- .stream => |stream| blk: {
- const writeFn = stream.writeFn orelse return err_unsupported;
- break :blk writeFn(bytes);
+ .stream => |stream| {
+ const writeFn = stream.writeFn orelse return Error.WriteNotSupported;
+ proc.state = .suspended;
+ try call(self.inode.pid, writeFn, .{bytes}, .{
+ .hookFn = crossProcessReturn,
+ .context = proc,
+ });
},
- .hook => err_unsupported,
- else => err_unsupported,
+ .hook => Error.WriteNotSupported,
+ else => Error.WriteNotSupported,
};
}
};
@@ -188,7 +194,7 @@ pub fn find(path: []const u8) ?*Node {
return &root;
}
-pub fn provideResource(path: []const u8, resource: Resource) !void {
+pub fn provideResource(path: []const u8, resource: Resource, pid: u16) !void {
if (!std.fs.path.isAbsolutePosix(path)) return Error.RelativePathNotAllowed;
const dirname = std.fs.path.dirnamePosix(path) orelse return Error.NoAbsoluteContainingDirectory;
@@ -197,24 +203,47 @@ pub fn provideResource(path: []const u8, resource: Resource) !void {
.dir => |*dir| dir.provideResource(.{
.name = std.fs.path.basenamePosix(path),
.resource = resource,
+ .pid = pid,
}),
else => Error.NotADirectory,
};
} else return Error.NotFound;
}
-pub fn provideResourceZ(path_c: [*:0]const u8, resource: Resource) !void {
- return provideResource(mem.sliceTo(path_c, 0), resource);
+pub fn provideResourceZ(path_c: [*:0]const u8, resource: Resource, pid: u16) !void {
+ return provideResource(mem.sliceTo(path_c, 0), resource, pid);
}
-pub fn open(path: []const u8, pid: u16, data: usize) !UserInfo {
+pub fn open(proc: *process.Info, path: []const u8, pid: u16, data: usize) !ResourceDescriptor {
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) },
+ .hook => |hook| {
+ proc.state = .suspended;
+ try call(node.data.pid, hook.callback, .{ pid, data }, .{
+ .hookFn = crossProcessReturn,
+ .context = proc,
+ });
+ },
+ else => 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);
+pub fn openZ(proc: *process.Info, path_c: [*:0]const u8, pid: u16, data: usize) !ResourceDescriptor {
+ return open(proc, mem.sliceTo(path_c, 0), pid, data);
+}
+
+fn call(pid: u16, function: *const anyopaque, args: anytype, termHook: ?process.Info.TermHook) !noreturn {
+ const proc = process.latestThread(pid).?;
+ const callback_thread = try proc.createThread(null);
+
+ callback_thread.call(@intFromPtr(function), args, termHook);
+}
+
+fn crossProcessReturn(context: *anyopaque, driver: *const process.Info) void {
+ const proc: *process.Info = @alignCast(@ptrCast(context));
+ proc.trap_frame.general_purpose_registers[10] = driver.trap_frame.general_purpose_registers[10];
+ proc.trap_frame.general_purpose_registers[11] = driver.trap_frame.general_purpose_registers[11];
+ proc.pc += 4; // Skip ecall instruction
+ proc.state = .waiting;
+ // Scheduler is called by the "terminate" syscall after two layers of returning.
}