From 577ed9e01a83c13bf151b5137e6fe1eace1c4f7c Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Mon, 2 May 2022 19:25:02 +0200
Subject: syscalls: fork() noreap flag

---
 src/kernel/proc.c     |  6 ++++--
 src/kernel/proc.h     |  3 ++-
 src/kernel/syscalls.c | 10 +++++-----
 3 files changed, 11 insertions(+), 8 deletions(-)

(limited to 'src/kernel')

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