aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2024-07-17 13:04:00 +0200
committerHimbeer <himbeer@disroot.org>2024-07-17 13:04:00 +0200
commit624954ef5fc395012825577abea46ec73d24ef6a (patch)
tree58f372d69867bff4ab10acccdcc4fb36417f53d6
parented35a9acf154f4b90b06602b648fe916ec442cc5 (diff)
process: Detach or orphan provided resources on termination
Fixes #42.
-rw-r--r--src/lib/process.zig6
-rw-r--r--src/lib/resources.zig12
-rw-r--r--src/lib/syscall.zig60
-rw-r--r--src/lib/sysexchange.zig6
-rw-r--r--src/lib/vfs.zig53
5 files changed, 113 insertions, 24 deletions
diff --git a/src/lib/process.zig b/src/lib/process.zig
index dcb1baa..a4bbb75 100644
--- a/src/lib/process.zig
+++ b/src/lib/process.zig
@@ -7,6 +7,7 @@ const std = @import("std");
const instructions = @import("instructions.zig");
const paging = @import("paging.zig");
+const sysexchange = @import("sysexchange.zig");
const time = @import("sbi/time.zig");
const trap = @import("trap.zig");
const vfs = @import("vfs.zig");
@@ -171,6 +172,10 @@ pub const Info = struct {
var node = list.first;
while (node) |proc_node| : (node = proc_node.next) {
if (self.shouldRemove(&proc_node.data)) {
+ if (proc_node.data.thread_id != self.thread_id) {
+ proc_node.data.terminate();
+ }
+
list.remove(proc_node);
self.allocator.destroy(proc_node);
}
@@ -194,6 +199,7 @@ pub const Info = struct {
cleanup_hook.cleanupFn(self, cleanup_hook.buffer, cleanup_hook.copy);
}
if (self.term_hook) |term_hook| {
+ sysexchange.frameReturn(void, &self.trap_frame, vfs.Error.Detached);
term_hook.hookFn(term_hook.context, self);
}
}
diff --git a/src/lib/resources.zig b/src/lib/resources.zig
index c79c82e..f73c751 100644
--- a/src/lib/resources.zig
+++ b/src/lib/resources.zig
@@ -67,7 +67,9 @@ fn provideConsole() !void {
.writeFn = iofs.debug.write,
},
},
- }, 0);
+ }, 0, .{
+ .reclaimable = false,
+ });
}
fn provideUserinit() !void {
@@ -110,7 +112,9 @@ fn addFile(path: []const u8, file: File) !void {
.initializer = initializer,
},
},
- }, 0);
+ }, 0, .{
+ .reclaimable = false,
+ });
}
fn addDir(path: []const u8) !void {
@@ -121,7 +125,9 @@ fn addDir(path: []const u8) !void {
try vfs.provideResource(path, .{
.tag = .dir,
.data = .{ .dir = tree },
- }, 0);
+ }, 0, .{
+ .reclaimable = false,
+ });
}
fn open(initializer: ?*anyopaque, _: u16) callconv(.C) Result(*anyopaque) {
diff --git a/src/lib/syscall.zig b/src/lib/syscall.zig
index 661c98d..1533cd4 100644
--- a/src/lib/syscall.zig
+++ b/src/lib/syscall.zig
@@ -74,6 +74,7 @@ fn close(proc: *process.Info, trap_frame: *const trap.Frame) void {
// provideStream(
// path_c: [*:0]const u8, // fixme: Kernel panic if null pointer
+// options: *const vfs.Options, // fixme: Kernel panic if null pointer
// readFn: ?vfs.Stream.ReadFn,
// writeFn: ?vfs.Stream.WriteFn,
// ) Result(void)
@@ -82,8 +83,9 @@ fn provideStream(proc: *const process.Info, trap_frame: *trap.Frame) void {
defer paging.setUserMemoryAccess(false);
const path_c: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
- const readFn: ?vfs.Stream.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[11]);
- const writeFn: ?vfs.Stream.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[12]);
+ const options: *const vfs.Options = @ptrFromInt(trap_frame.general_purpose_registers[11]);
+ const readFn: ?vfs.Stream.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[12]);
+ const writeFn: ?vfs.Stream.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[13]);
sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path_c, .{
.tag = .stream,
@@ -91,11 +93,12 @@ fn provideStream(proc: *const process.Info, trap_frame: *trap.Frame) void {
.readFn = readFn,
.writeFn = writeFn,
} },
- }, proc.id));
+ }, proc.id, options.*));
}
// provideFile(
// path_c: [*:0]const u8, // fixme: Kernel panic if null pointer
+// options: *const vfs.Options, // fixme: Kernel panic if null pointer
// openFn: vfs.File.OpenFn,
// readFn: ?vfs.File.ReadFn,
// writeFn: ?vfs.File.WriteFn,
@@ -106,10 +109,11 @@ fn provideFile(proc: *const process.Info, trap_frame: *trap.Frame) void {
defer paging.setUserMemoryAccess(false);
const path_c: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
- const openFn: vfs.File.OpenFn = @ptrFromInt(trap_frame.general_purpose_registers[11]);
- const readFn: ?vfs.File.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[12]);
- const writeFn: ?vfs.File.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[13]);
- const closeFn: ?vfs.File.CloseFn = @ptrFromInt(trap_frame.general_purpose_registers[14]);
+ const options: *const vfs.Options = @ptrFromInt(trap_frame.general_purpose_registers[11]);
+ const openFn: vfs.File.OpenFn = @ptrFromInt(trap_frame.general_purpose_registers[12]);
+ const readFn: ?vfs.File.ReadFn = @ptrFromInt(trap_frame.general_purpose_registers[13]);
+ const writeFn: ?vfs.File.WriteFn = @ptrFromInt(trap_frame.general_purpose_registers[14]);
+ const closeFn: ?vfs.File.CloseFn = @ptrFromInt(trap_frame.general_purpose_registers[15]);
sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path_c, .{
.tag = .file,
@@ -120,11 +124,12 @@ fn provideFile(proc: *const process.Info, trap_frame: *trap.Frame) void {
.closeFn = closeFn,
.initializer = null,
} },
- }, proc.id));
+ }, proc.id, options.*));
}
// provideHook(
// path_c: [*:0]const u8, // fixme: Kernel panic if null pointer
+// options: *const vfs.Options, // fixme: Kernel panic if null pointer,
// callback: vfs.Hook.Callback,
// ) Result(void)
fn provideHook(proc: *const process.Info, trap_frame: *trap.Frame) void {
@@ -132,14 +137,15 @@ fn provideHook(proc: *const process.Info, trap_frame: *trap.Frame) void {
defer paging.setUserMemoryAccess(false);
const path_c: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
- const callback: vfs.Hook.Callback = @ptrFromInt(trap_frame.general_purpose_registers[11]);
+ const options: *const vfs.Options = @ptrFromInt(trap_frame.general_purpose_registers[11]);
+ const callback: vfs.Hook.Callback = @ptrFromInt(trap_frame.general_purpose_registers[12]);
sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path_c, .{
.tag = .hook,
.data = .{ .hook = .{
.callback = callback,
} },
- }, proc.id));
+ }, proc.id, options.*));
}
// mkdir(
@@ -158,11 +164,14 @@ fn mkdir(proc: *const process.Info, trap_frame: *trap.Frame) void {
sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path_c, .{
.tag = .dir,
.data = .{ .dir = tree },
- }, proc.id));
+ }, proc.id, .{
+ .reclaimable = false,
+ }));
}
// provideDirHook(
// path_c: [*:0]const u8, // fixme: Kernel panic if null pointer
+// options: *const vfs.Options, // fixme: Kernel panic if null pointer
// provideFn: vfs.DirHook.ProvideFn,
// findFn: vfs.DirHook.FindFn,
// removeFn: vfs.DirHook.RemoveFn,
@@ -172,9 +181,10 @@ fn provideDirHook(proc: *const process.Info, trap_frame: *trap.Frame) void {
defer paging.setUserMemoryAccess(false);
const path_c: [*:0]const u8 = @ptrFromInt(trap_frame.general_purpose_registers[10]);
- const provideFn: vfs.DirHook.ProvideFn = @ptrFromInt(trap_frame.general_purpose_registers[11]);
- const findFn: vfs.DirHook.FindFn = @ptrFromInt(trap_frame.general_purpose_registers[12]);
- const removeFn: vfs.DirHook.RemoveFn = @ptrFromInt(trap_frame.general_purpose_registers[13]);
+ const options: *const vfs.Options = @ptrFromInt(trap_frame.general_purpose_registers[11]);
+ const provideFn: vfs.DirHook.ProvideFn = @ptrFromInt(trap_frame.general_purpose_registers[12]);
+ const findFn: vfs.DirHook.FindFn = @ptrFromInt(trap_frame.general_purpose_registers[13]);
+ const removeFn: vfs.DirHook.RemoveFn = @ptrFromInt(trap_frame.general_purpose_registers[14]);
sysexchange.frameReturn(null, trap_frame, vfs.provideResourceZ(path_c, .{
.tag = .dir_hook,
@@ -183,7 +193,7 @@ fn provideDirHook(proc: *const process.Info, trap_frame: *trap.Frame) void {
.findFn = findFn,
.removeFn = removeFn,
} },
- }, proc.id));
+ }, proc.id, options.*));
}
// remove(path_c: [*:0]const u8) Result(void) // fixme: Kernel panic if null pointer
@@ -225,7 +235,15 @@ fn read(proc: *process.Info, trap_frame: *trap.Frame) void {
sysexchange.frameReturn(usize, trap_frame, process.Error.BadRdHandle);
return;
};
- sysexchange.frameReturn(usize, trap_frame, rd.read(proc, buffer[0..len]));
+
+ const result = rd.read(proc, buffer[0..len]) catch |err| blk: {
+ if (err == vfs.Error.Orphaned) {
+ proc.destroyRdHandle(handle);
+ }
+
+ break :blk err;
+ };
+ sysexchange.frameReturn(usize, trap_frame, result);
}
// write(handle: usize, bytes: [*]const u8, len: usize) Result(usize)
@@ -241,7 +259,15 @@ fn write(proc: *process.Info, trap_frame: *trap.Frame) void {
sysexchange.frameReturn(usize, trap_frame, process.Error.BadRdHandle);
return;
};
- sysexchange.frameReturn(usize, trap_frame, rd.write(proc, bytes[0..len]));
+
+ const result = rd.write(proc, bytes[0..len]) catch |err| blk: {
+ if (err == vfs.Error.Orphaned) {
+ proc.destroyRdHandle(handle);
+ }
+
+ break :blk err;
+ };
+ sysexchange.frameReturn(usize, trap_frame, result);
}
// terminate() noreturn
diff --git a/src/lib/sysexchange.zig b/src/lib/sysexchange.zig
index 3dd93df..c3d7fa4 100644
--- a/src/lib/sysexchange.zig
+++ b/src/lib/sysexchange.zig
@@ -63,6 +63,8 @@ pub const Status = enum(usize) {
read_not_supported,
write_not_supported,
in_use,
+ detached,
+ orphaned,
unknown = std.math.maxInt(usize),
pub fn fromError(err: anyerror) Status {
@@ -122,6 +124,8 @@ pub const Status = enum(usize) {
error.ReadNotSupported => .read_not_supported,
error.WriteNotSupported => .write_not_supported,
error.InUse => .in_use,
+ error.Detached => .detached,
+ error.Orphaned => .orphaned,
else => .unknown,
};
}
@@ -186,6 +190,8 @@ pub const Status = enum(usize) {
.read_not_supported => error.ReadNotSupported,
.write_not_supported => error.WriteNotSupported,
.in_use => error.InUse,
+ .detached => error.Detached,
+ .orphaned => error.Orphaned,
.unknown => error.Unknown,
};
}
diff --git a/src/lib/vfs.zig b/src/lib/vfs.zig
index f3520be..c8cc552 100644
--- a/src/lib/vfs.zig
+++ b/src/lib/vfs.zig
@@ -10,7 +10,22 @@ const sysexchange = @import("sysexchange.zig");
const mem = std.mem;
-var root: Node = .{ .data = .{ .name = "", .inode = .{ .resource = .{ .tag = .dir, .data = .{ .dir = undefined } }, .pid = 0 } } };
+var root: Node = .{
+ .data = .{
+ .name = "",
+ .inode = .{
+ .resource = .{
+ .tag = .dir,
+ .data = .{ .dir = undefined },
+ },
+ .pid = 0,
+ .options = .{
+ .reclaimable = false,
+ },
+ .flags = .{},
+ },
+ },
+};
pub fn treeRoot() *const Tree {
return root.data.inode.resource.data.dir;
@@ -25,6 +40,8 @@ pub const Error = error{
ReadNotSupported,
WriteNotSupported,
InUse,
+ Detached,
+ Orphaned,
};
// A stream is a resource that provides a shared data stream with a driver.
@@ -91,6 +108,16 @@ pub const Inode = extern struct {
resource: Resource,
refs: usize = 0,
pid: u16,
+ options: Options,
+ flags: Flags,
+};
+
+pub const Options = extern struct {
+ reclaimable: bool,
+};
+
+pub const Flags = extern struct {
+ detached: bool = false,
};
pub const DirEntry = struct {
@@ -151,6 +178,13 @@ pub const ResourceDescriptor = struct {
}
pub fn read(self: ResourceDescriptor, proc: *process.Info, buffer: []u8) !usize {
+ if (self.inode.flags.detached and self.inode.options.reclaimable) {
+ return Error.Detached;
+ }
+ if (self.inode.flags.detached and !self.inode.options.reclaimable) {
+ return Error.Orphaned;
+ }
+
return switch (self.inode.resource.tag) {
.stream => {
const stream = self.inode.resource.data.stream;
@@ -179,6 +213,13 @@ pub const ResourceDescriptor = struct {
}
pub fn write(self: ResourceDescriptor, proc: *process.Info, bytes: []const u8) !usize {
+ if (self.inode.flags.detached and self.inode.options.reclaimable) {
+ return Error.Detached;
+ }
+ if (self.inode.flags.detached and !self.inode.options.reclaimable) {
+ return Error.Orphaned;
+ }
+
return switch (self.inode.resource.tag) {
.stream => {
const stream = self.inode.resource.data.stream;
@@ -256,7 +297,7 @@ pub fn find(path: []const u8) ?*Inode {
return &root.data.inode;
}
-pub fn provideResource(path: []const u8, resource: Resource, pid: u16) !void {
+pub fn provideResource(path: []const u8, resource: Resource, pid: u16, options: Options) !void {
if (!std.fs.path.isAbsolutePosix(path)) return Error.RelativePathNotAllowed;
const dirname = std.fs.path.dirnamePosix(path) orelse return Error.NoAbsoluteContainingDirectory;
@@ -271,6 +312,8 @@ pub fn provideResource(path: []const u8, resource: Resource, pid: u16) !void {
.inode = .{
.resource = resource,
.pid = pid,
+ .options = options,
+ .flags = .{},
},
});
},
@@ -280,6 +323,8 @@ pub fn provideResource(path: []const u8, resource: Resource, pid: u16) !void {
break :blk dir_hook.provideFn(basename.ptr, basename.len, .{
.resource = resource,
.pid = pid,
+ .options = options,
+ .flags = .{},
}).toErrorUnion();
},
else => Error.NotADirectory,
@@ -287,8 +332,8 @@ pub fn provideResource(path: []const u8, resource: Resource, pid: u16) !void {
} else return Error.NotFound;
}
-pub fn provideResourceZ(path_c: [*:0]const u8, resource: Resource, pid: u16) !void {
- return provideResource(mem.sliceTo(path_c, 0), resource, pid);
+pub fn provideResourceZ(path_c: [*:0]const u8, resource: Resource, pid: u16, options: Options) !void {
+ return provideResource(mem.sliceTo(path_c, 0), resource, pid, options);
}
pub fn open(proc: *process.Info, path: []const u8, pid: u16, data: usize) !ResourceDescriptor {