From 2373680d99372b9e7cdecf1c8d4b0a7366eb3cfb Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Tue, 21 Sep 2021 17:48:52 +0200
Subject: refactor `await_finish` into `process_try2collect`

the new name is terrible, but at least the function now has a clear
purpose
---
 src/kernel/proc.c     | 28 ++++++++++++++++++++++++++++
 src/kernel/proc.h     |  4 ++++
 src/kernel/syscalls.c | 31 ++++++-------------------------
 3 files changed, 38 insertions(+), 25 deletions(-)

(limited to 'src/kernel')

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;
 	}
-- 
cgit v1.2.3