diff options
author | dzwdz | 2021-09-21 17:48:52 +0200 |
---|---|---|
committer | dzwdz | 2021-09-21 17:48:52 +0200 |
commit | 2373680d99372b9e7cdecf1c8d4b0a7366eb3cfb (patch) | |
tree | 93069f4e46428d6bb1055d1c999c527e87f49a35 /src | |
parent | d34bd9a45440be2ef65d24619af5505b8c05c229 (diff) |
refactor `await_finish` into `process_try2collect`
the new name is terrible, but at least the function now has a clear
purpose
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/proc.c | 28 | ||||
-rw-r--r-- | src/kernel/proc.h | 4 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 31 |
3 files changed, 38 insertions, 25 deletions
diff --git a/src/kernel/proc.c b/src/kernel/proc.c index df20df3..94fc419 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -1,5 +1,6 @@ #include <kernel/arch/generic.h> #include <kernel/mem/alloc.h> +#include <kernel/mem/virt.h> #include <kernel/panic.h> #include <kernel/proc.h> #include <kernel/util.h> @@ -101,3 +102,30 @@ handle_t process_find_handle(struct process *proc) { if (handle == HANDLE_MAX) handle = -1; return handle; } + +int process_try2collect(struct process *dead) { + struct process *parent = dead->parent; + int len, ret; + bool res; + + assert(dead->state == PS_DEAD); + + switch (parent->state) { + case PS_WAITS4CHILDDEATH: + dead->state = PS_DEADER; + parent->state = PS_RUNNING; + + len = parent->death_msg.len < dead->death_msg.len + ? parent->death_msg.len : dead->death_msg.len; + res = virt_cpy( + parent->pages, parent->death_msg.buf, + dead->pages, dead->death_msg.buf, len); + + ret = res ? len : 0; + regs_savereturn(&parent->regs, ret); + return ret; + + default: + return -1; + } +} diff --git a/src/kernel/proc.h b/src/kernel/proc.h index 0e02d27..82bb59a 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -55,3 +55,7 @@ _Noreturn void process_switch_any(void); // switches to any running process struct process *process_find(enum process_state); handle_t process_find_handle(struct process *proc); // finds the first free handle + +/** Tries to transistion from PS_DEAD to PS_DEADER. + * @return a nonnegative length of the quit message if successful, a negative val otherwise*/ +int process_try2collect(struct process *dead); diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index ac21cdb..16238e7 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -8,33 +8,11 @@ #include <shared/syscalls.h> #include <stdint.h> -_Noreturn static void await_finish(struct process *dead, struct process *listener) { - int len; - bool res; - - assert(dead->state == PS_DEAD); - assert(listener->state == PS_WAITS4CHILDDEATH); - dead->state = PS_DEADER; - listener->state = PS_RUNNING; - - len = listener->death_msg.len < dead->death_msg.len - ? listener->death_msg.len : dead->death_msg.len; - res = virt_cpy( - listener->pages, listener->death_msg.buf, - dead->pages, dead->death_msg.buf, len); - regs_savereturn(&listener->regs, res ? len : -1); - process_switch(listener); -} - - _Noreturn void _syscall_exit(const char __user *msg, size_t len) { process_current->state = PS_DEAD; process_current->death_msg.buf = (userptr_t) msg; // discarding const process_current->death_msg.len = len; - - if (process_current->parent->state == PS_WAITS4CHILDDEATH) - await_finish(process_current, process_current->parent); - + process_try2collect(process_current); process_switch_any(); } @@ -47,8 +25,11 @@ int _syscall_await(char __user *buf, int len) { // find any already dead children for (struct process *iter = process_current->child; iter; iter = iter->sibling) { - if (iter->state == PS_DEAD) - await_finish(iter, process_current); // doesn't return + if (iter->state == PS_DEAD) { + int ret = process_try2collect(iter); + assert(ret >= 0); + return ret; + } if (iter->state != PS_DEADER) has_children = true; } |