summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/init/fs/misc.c4
-rw-r--r--src/init/main.c6
-rw-r--r--src/init/shell.c2
-rw-r--r--src/init/syscalls.c4
-rw-r--r--src/init/tests/main.c10
-rw-r--r--src/kernel/proc.c6
-rw-r--r--src/kernel/proc.h3
-rw-r--r--src/kernel/syscalls.c10
-rw-r--r--src/shared/syscalls.h4
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);