aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-07-17 22:32:03 +0200
committerHimbeer <himbeer@disroot.org>2024-07-17 22:32:03 +0200
commitce729578bd4fbf4108ebcdeda8186d606d1c803e (patch)
tree33413f3cbb84f977fad53eeef055e811062ff630 /src
parentb084e65f9f5d63b968081ecf82bf5d64d7d9f613 (diff)
syscall: Replace terminate() with /process/self/terminate VFS hook
Diffstat (limited to 'src')
-rw-r--r--src/lib/process.zig15
-rw-r--r--src/lib/resources.zig28
-rw-r--r--src/lib/rethooks.zig11
-rw-r--r--src/lib/syscall.zig9
-rw-r--r--src/lib/vfs.zig6
5 files changed, 55 insertions, 14 deletions
diff --git a/src/lib/process.zig b/src/lib/process.zig
index d7ecd5f..85d6522 100644
--- a/src/lib/process.zig
+++ b/src/lib/process.zig
@@ -458,6 +458,21 @@ fn usizeFromArg(arg: anytype) usize {
};
}
+pub fn findThread(pid: u16, thread_id: usize) ?*Info {
+ var node = list.first;
+ while (node) |proc_node| : (node = proc_node.next) {
+ if (proc_node.data.id == pid and proc_node.data.thread_id == thread_id) {
+ return &proc_node.data;
+ }
+ }
+
+ return null;
+}
+
+pub fn mainThread(pid: u16) ?*Info {
+ return findThread(pid, 0);
+}
+
pub fn latestThread(pid: u16) ?*Info {
var latest: ?*Info = null;
diff --git a/src/lib/resources.zig b/src/lib/resources.zig
index f73c751..92a28b6 100644
--- a/src/lib/resources.zig
+++ b/src/lib/resources.zig
@@ -45,6 +45,18 @@ const iofs = struct {
};
};
+const processfs = struct {
+ const self = struct {
+ fn terminate(pid: u16, thread_id: usize, _: usize) callconv(.C) sysexchange.Result(usize) {
+ const proc = process.findThread(pid, thread_id).?;
+ proc.terminate();
+ process.schedule() catch |err| {
+ std.debug.panic("Unable to schedule because all processes are terminated: {any}", .{err});
+ };
+ }
+ };
+};
+
pub const Error = error{
NoTarFileInitializer,
NoConsole,
@@ -53,9 +65,12 @@ pub const Error = error{
pub fn provideBuiltin() !void {
try addDir("/io");
try addDir("/userinit");
+ try addDir("/process");
+ try addDir("/process/self");
try provideConsole();
try provideUserinit();
+ try provideProcessSelf();
}
fn provideConsole() !void {
@@ -95,6 +110,19 @@ fn provideUserinit() !void {
}
}
+fn provideProcessSelf() !void {
+ try vfs.provideResource("/process/self/terminate", .{
+ .tag = .hook,
+ .data = .{
+ .hook = .{
+ .callback = processfs.self.terminate,
+ },
+ },
+ }, 0, .{
+ .reclaimable = false,
+ });
+}
+
fn addFile(path: []const u8, file: File) !void {
const allocator = vfs.treeRoot().allocator;
diff --git a/src/lib/rethooks.zig b/src/lib/rethooks.zig
index bad4d55..e81125a 100644
--- a/src/lib/rethooks.zig
+++ b/src/lib/rethooks.zig
@@ -3,9 +3,16 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pub fn terminate() linksection(".rethooks") callconv(.Naked) noreturn {
- // Syscall #100011 is "terminate".
+ // Syscall #100001 is "open".
+ // Use the "/process/self/terminate" hook to terminate the thread.
asm volatile (
- \\ li a7, 100011
+ \\ mv a0, a2
+ \\ mv a1, a3
+ \\ mv t0, a0
+ \\ li a7, 100001
\\ ecall
+ :
+ : [path_c] "{t0}" ("/process/self/terminate\x00".ptr),
+ : "a0", "a2", "a3", "a7"
);
}
diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig
index 1533cd4..5cbc9f2 100644
--- a/src/lib/syscall.zig
+++ b/src/lib/syscall.zig
@@ -32,7 +32,6 @@ pub fn handler(proc: *process.Info, trap_frame: *trap.Frame) !void {
100008 => remove(trap_frame),
100009 => read(proc, trap_frame),
100010 => write(proc, trap_frame),
- 100011 => terminate(proc),
else => return HandleError.UnknownSyscall,
}
}
@@ -269,11 +268,3 @@ fn write(proc: *process.Info, trap_frame: *trap.Frame) void {
};
sysexchange.frameReturn(usize, trap_frame, result);
}
-
-// terminate() noreturn
-fn terminate(proc: *process.Info) noreturn {
- proc.terminate();
- process.schedule() catch |err| {
- std.debug.panic("Unable to schedule because all processes are terminated: {any}", .{err});
- };
-}
diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig
index 71dda98..46f01d6 100644
--- a/src/lib/vfs.zig
+++ b/src/lib/vfs.zig
@@ -72,7 +72,7 @@ pub const File = extern struct {
pub const Hook = extern struct {
callback: Callback,
- pub const Callback = *allowzero const fn (pid: u16, data: usize) callconv(.C) sysexchange.Result(usize);
+ pub const Callback = *allowzero const fn (pid: u16, thread_id: usize, data: usize) callconv(.C) sysexchange.Result(usize);
};
// A directory hook is a resource that provides other resources via driver callbacks.
@@ -380,8 +380,8 @@ fn call(proc: *process.Info, function: *const anyopaque, args: anytype, cleanup_
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.trap_frame.general_purpose_registers[10] = driver.trap_frame.general_purpose_registers[12];
+ proc.trap_frame.general_purpose_registers[11] = driver.trap_frame.general_purpose_registers[13];
proc.pc += 4; // Skip ecall instruction
proc.state = .waiting;
// Scheduler is called by the "terminate" syscall after two layers of returning.