diff options
author | dzwdz | 2022-05-02 19:25:02 +0200 |
---|---|---|
committer | dzwdz | 2022-05-02 19:25:02 +0200 |
commit | 577ed9e01a83c13bf151b5137e6fe1eace1c4f7c (patch) | |
tree | 750dd8a3536ce70d817e6920c89042ee94899a29 /src | |
parent | d9dc6a0c4c5047c3789a16ef623eeff7c240f5a9 (diff) |
syscalls: fork() noreap flag
Diffstat (limited to 'src')
-rw-r--r-- | src/init/fs/misc.c | 4 | ||||
-rw-r--r-- | src/init/main.c | 6 | ||||
-rw-r--r-- | src/init/shell.c | 2 | ||||
-rw-r--r-- | src/init/syscalls.c | 4 | ||||
-rw-r--r-- | src/init/tests/main.c | 10 | ||||
-rw-r--r-- | src/kernel/proc.c | 6 | ||||
-rw-r--r-- | src/kernel/proc.h | 3 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 10 | ||||
-rw-r--r-- | src/shared/syscalls.h | 4 |
9 files changed, 27 insertions, 22 deletions
diff --git a/src/init/fs/misc.c b/src/init/fs/misc.c index b962b64..ca3128d 100644 --- a/src/init/fs/misc.c +++ b/src/init/fs/misc.c @@ -53,7 +53,7 @@ static void fs_respond_delegate(struct fs_wait_response *res, handle_t delegate, switch (res->op) { case VFSOP_READ: - if (_syscall_fork()) { + if (_syscall_fork(FORK_NOREAP)) { // handle reads in a child // this is a HORRIBLE workaround for making concurrent IO work without proper delegates break; @@ -62,7 +62,7 @@ static void fs_respond_delegate(struct fs_wait_response *res, handle_t delegate, size = res->capacity < sizeof(buf) ? res->capacity : sizeof(buf); ret = _syscall_read(delegate, buf, size, res->offset); _syscall_fs_respond(buf, ret); - _syscall_exit(0); // TODO unreapable - add a nonblocking reap syscall + _syscall_exit(0); break; // TODO proper writing (see above) diff --git a/src/init/main.c b/src/init/main.c index 5601526..5db1333 100644 --- a/src/init/main.c +++ b/src/init/main.c @@ -28,7 +28,7 @@ int main(void) { MOUNT("/bind/", fs_passthru(NULL)); - if (_syscall_fork()) { + if (_syscall_fork(0)) { /* (used to) expose a bug in the kernel * the program will flow like this: * 1. we launch the forked init @@ -45,7 +45,7 @@ int main(void) { _syscall_exit(1); } - if (!_syscall_fork()) { + if (!_syscall_fork(0)) { if (file_open(&__stdout, "/com1") < 0 || file_open(&__stdin, "/com1") < 0) _syscall_exit(1); @@ -54,7 +54,7 @@ int main(void) { } - if (!_syscall_fork()) { + if (!_syscall_fork(0)) { if (file_open(&__stdout, "/vga_tty") < 0) _syscall_exit(1); diff --git a/src/init/shell.c b/src/init/shell.c index d723731..e7c836f 100644 --- a/src/init/shell.c +++ b/src/init/shell.c @@ -145,7 +145,7 @@ void shell_loop(void) { } else if (!strcmp(cmd, "exit")) { _syscall_exit(0); } else if (!strcmp(cmd, "fork")) { - if (_syscall_fork()) + if (_syscall_fork(0)) _syscall_await(); else level++; } else if (!strcmp(cmd, "run_tests")) { diff --git a/src/init/syscalls.c b/src/init/syscalls.c index 15acd1c..a374976 100644 --- a/src/init/syscalls.c +++ b/src/init/syscalls.c @@ -6,8 +6,8 @@ _Noreturn void _syscall_exit(int ret) { __builtin_unreachable(); } -int _syscall_fork(void) { - return _syscall(_SYSCALL_FORK, 0, 0, 0, 0); +int _syscall_fork(int flags) { + return _syscall(_SYSCALL_FORK, flags, 0, 0, 0); } int _syscall_await(void) { diff --git a/src/init/tests/main.c b/src/init/tests/main.c index ed50229..ac8874f 100644 --- a/src/init/tests/main.c +++ b/src/init/tests/main.c @@ -12,7 +12,7 @@ #define assert(cond) if (!(cond)) test_fail(); static void run_forked(void (*fn)()) { - if (!_syscall_fork()) { + if (!_syscall_fork(0)) { fn(); _syscall_exit(0); } else { @@ -31,7 +31,7 @@ static void test_await(void) { int counts[16] = {0}; for (int i = 0; i < 16; i++) - if (!_syscall_fork()) + if (!_syscall_fork(0)) _syscall_exit(i); while ((ret = _syscall_await()) != ~0) { @@ -49,12 +49,12 @@ static void test_faults(void) { * reap all its children */ int await_cnt = 0; - if (!_syscall_fork()) { // invalid memory access + if (!_syscall_fork(0)) { // invalid memory access asm volatile("movb $69, 0" ::: "memory"); printf("this shouldn't happen"); _syscall_exit(-1); } - if (!_syscall_fork()) { // #GP + if (!_syscall_fork(0)) { // #GP asm volatile("hlt" ::: "memory"); printf("this shouldn't happen"); _syscall_exit(-1); @@ -94,7 +94,7 @@ static void test_orphaned_fs(void) { static void stress_fork(void) { /* run a lot of processes */ for (size_t i = 0; i < 2048; i++) { - if (!_syscall_fork()) _syscall_exit(0); + if (!_syscall_fork(0)) _syscall_exit(0); _syscall_await(); } } diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 838d520..4dfee15 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -6,6 +6,7 @@ #include <kernel/proc.h> #include <kernel/vfs/mount.h> #include <shared/mem.h> +#include <shared/syscalls.h> #include <stdint.h> struct process *process_first; @@ -49,7 +50,7 @@ struct process *process_seed(struct kmain_info *info) { return process_first; } -struct process *process_fork(struct process *parent) { +struct process *process_fork(struct process *parent, int flags) { struct process *child = kmalloc(sizeof *child); memcpy(child, parent, sizeof *child); @@ -58,6 +59,7 @@ struct process *process_fork(struct process *parent) { child->child = NULL; child->parent = parent; parent->child = child; + child->noreap = (flags & FORK_NOREAP) > 0; parent->handled_req = NULL; // TODO control this with a flag @@ -325,7 +327,7 @@ int process_try2collect(struct process *dead) { assert(dead->state == PS_DEAD); - if (!parent) { + if (!parent || dead->noreap) { process_transition(dead, PS_DEADER); return -1; } diff --git a/src/kernel/proc.h b/src/kernel/proc.h index 26227e1..c592fd7 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -25,6 +25,7 @@ struct process { enum process_state state; bool deathbed; // kill on next process_switch attempt + bool noreap; struct process *sibling; struct process *child; @@ -64,7 +65,7 @@ extern struct process *process_current; // creates the root process struct process *process_seed(struct kmain_info *info); -struct process *process_fork(struct process *parent); +struct process *process_fork(struct process *parent, int flags); void process_forget(struct process *); // remove references to process void process_free(struct process *); diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index ffacdbc..57286f1 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -21,7 +21,7 @@ int _syscall_await(void) { // find any already dead children for (struct process *iter = process_current->child; iter; iter = iter->sibling) { - if (iter->state == PS_DEAD) + if (iter->state == PS_DEAD && !iter->noreap) return process_try2collect(iter); if (iter->state != PS_DEADER) has_children = true; @@ -35,8 +35,8 @@ int _syscall_await(void) { } } -int _syscall_fork(void) { - struct process *child = process_fork(process_current); +int _syscall_fork(int flags) { + struct process *child = process_fork(process_current, flags); regs_savereturn(&child->regs, 0); return 1; } @@ -180,7 +180,7 @@ handle_t _syscall_fs_fork2(void) { backend->handler = NULL; backend->queue = NULL; - child = process_fork(process_current); + child = process_fork(process_current, 0); child->controlled = backend; regs_savereturn(&child->regs, 0); @@ -249,7 +249,7 @@ int _syscall(int num, int a, int b, int c, int d) { case _SYSCALL_AWAIT: return _syscall_await(); case _SYSCALL_FORK: - return _syscall_fork(); + return _syscall_fork(a); case _SYSCALL_OPEN: return _syscall_open((userptr_t)a, b); case _SYSCALL_MOUNT: diff --git a/src/shared/syscalls.h b/src/shared/syscalls.h index 9b250ab..5773190 100644 --- a/src/shared/syscalls.h +++ b/src/shared/syscalls.h @@ -2,6 +2,8 @@ #include <shared/types.h> #include <stddef.h> +#define FORK_NOREAP 1 + enum { // idc about stable syscall numbers just yet _SYSCALL_EXIT, @@ -38,7 +40,7 @@ int _syscall_await(void); * All user memory pages get copied too. * @return 0 in the child, a meaningless positive value in the parent. */ -int _syscall_fork(void); +int _syscall_fork(int flags); handle_t _syscall_open(const char __user *path, int len); |