diff --git a/kernel-src/arch/x86-64/syscall.asm b/kernel-src/arch/x86-64/syscall.asm index 41c30157..7555fb0e 100644 --- a/kernel-src/arch/x86-64/syscall.asm +++ b/kernel-src/arch/x86-64/syscall.asm @@ -12,6 +12,7 @@ extern syscall_fstat extern syscall_fstatat extern syscall_fork extern syscall_execve +extern syscall_exit syscalltab: dq syscall_print dq syscall_mmap @@ -26,7 +27,8 @@ dq syscall_fstat dq syscall_fstatat dq syscall_fork dq syscall_execve -syscallcount equ 13 +dq syscall_exit +syscallcount equ 14 section .text global arch_syscall_entry ; on entry: diff --git a/kernel-src/include/kernel/scheduler.h b/kernel-src/include/kernel/scheduler.h index 719e2815..81274101 100644 --- a/kernel-src/include/kernel/scheduler.h +++ b/kernel-src/include/kernel/scheduler.h @@ -5,12 +5,16 @@ #include #include #include +#include #define SCHED_THREAD_FLAGS_QUEUED 1 #define SCHED_THREAD_FLAGS_RUNNING 2 #define SCHED_THREAD_FLAGS_SLEEP 4 #define SCHED_THREAD_FLAGS_INTERRUPTIBLE 8 +#define SCHED_PROC_STATE_NORMAL 0 +#define SCHED_PROC_STATE_ZOMBIE 1 + #define STACK_TOP (void *)0x0000800000000000 #define INTERP_BASE (void *)0x00000beef0000000 @@ -39,6 +43,8 @@ typedef struct thread_t { typedef struct proc_t { spinlock_t lock; + int status; + int state; struct proc_t *sibling; struct proc_t *parent; struct proc_t *child; @@ -56,13 +62,16 @@ typedef struct proc_t { vnode_t *cwd; vnode_t *root; spinlock_t nodeslock; + semaphore_t waitsem; } proc_t; #include +extern proc_t *sched_initproc; + void sched_init(); void sched_runinit(); -void sched_threadexit(); +__attribute__((noreturn)) void sched_threadexit(); void sched_queue(thread_t *thread); void sched_stopcurrentthread(); int sched_yield(); diff --git a/kernel-src/sys/scheduler.c b/kernel-src/sys/scheduler.c index 845cdddc..52d886d4 100644 --- a/kernel-src/sys/scheduler.c +++ b/kernel-src/sys/scheduler.c @@ -8,6 +8,7 @@ #include #include #include +#include #define QUANTUM_US 100000 #define SCHEDULER_STACK_SIZE 4096 @@ -26,6 +27,7 @@ static rqueue_t runqueue[RUNQUEUE_COUNT]; static uint64_t runqueuebitmap; static spinlock_t runqueuelock; +proc_t *sched_initproc; static pid_t currpid = 1; proc_t *sched_newproc() { @@ -46,6 +48,7 @@ proc_t *sched_newproc() { proc->fdcount = 3; proc->fdfirst = 3; SPINLOCK_INIT(proc->fdlock); + SEMAPHORE_INIT(&proc->waitsem, 0); proc->fd = alloc(sizeof(fd_t) * 3); if (proc->fd == NULL) { @@ -189,31 +192,13 @@ __attribute__((noreturn)) void sched_stopcurrentthread() { switchthread(next); } -void sched_threadexit() { +__attribute__((noreturn)) void sched_threadexit() { interrupt_set(false); thread_t *thread = _cpu()->thread; proc_t *proc = thread->proc; - if (proc) { - spinlock_acquire(&proc->lock); - - int toffset = -1; - - for (int i = 0; i < proc->threadtablesize; ++i) { - if (proc->threads[i] == thread) { - toffset = i; - break; - } - } - - __assert(toffset != -1); - --proc->runningthreadcount; - - if (proc->runningthreadcount == 0) { - // TODO prepare proc state to be left as a zombie - } - spinlock_release(&proc->lock); - } + if (proc) + __atomic_fetch_sub(&currpid, 1, __ATOMIC_SEQ_CST); _cpu()->thread = NULL; @@ -373,6 +358,8 @@ void sched_runinit() { proc_t *proc = sched_newproc(); __assert(proc); + sched_initproc = proc; + vnode_t *initnode; __assert(vfs_open(vfsroot, "/usr/bin/bash", 0, &initnode) == 0); diff --git a/kernel-src/sys/syscalls/exit.c b/kernel-src/sys/syscalls/exit.c new file mode 100644 index 00000000..b163a7ac --- /dev/null +++ b/kernel-src/sys/syscalls/exit.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include + +__attribute__((noreturn)) void syscall_exit(context_t *context, int status) { + thread_t *thread = _cpu()->thread; + proc_t *proc = thread->proc; + __assert(proc != sched_initproc); + + // TODO stop other threads + + for (int fd = 0; fd < proc->fdcount; ++fd) + fd_close(fd); + + spinlock_acquire(&proc->lock); + + VOP_RELEASE(proc->root); + VOP_RELEASE(proc->cwd); + + proc->status = status; + proc->state = SCHED_PROC_STATE_ZOMBIE; + proc_t *lastchild = proc->child; + + spinlock_acquire(&sched_initproc->lock); + + bool haszombie = false; + + while (lastchild && lastchild->sibling) { + if (lastchild->state == SCHED_PROC_STATE_ZOMBIE) + haszombie = true; + + lastchild->parent = sched_initproc; + lastchild = lastchild->sibling; + } + + if (lastchild) { + if (lastchild->sibling->state == SCHED_PROC_STATE_ZOMBIE) + haszombie = true; + + lastchild->sibling = sched_initproc->child; + sched_initproc->child = proc->child; + } + + spinlock_release(&sched_initproc->lock); + spinlock_release(&proc->lock); + + semaphore_signal(&proc->parent->waitsem); + if (haszombie) + semaphore_signal(&sched_initproc->waitsem); + + sched_threadexit(); +} diff --git a/patches/mlibc/jinx-working-patch.patch b/patches/mlibc/jinx-working-patch.patch index a843d0fc..ae521d02 100644 --- a/patches/mlibc/jinx-working-patch.patch +++ b/patches/mlibc/jinx-working-patch.patch @@ -133,10 +133,10 @@ index 0000000..e5b087a + diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp new file mode 100644 -index 0000000..e108341 +index 0000000..f212b93 --- /dev/null +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp -@@ -0,0 +1,190 @@ +@@ -0,0 +1,189 @@ +#include +#include +#include @@ -244,8 +244,7 @@ index 0000000..e108341 + } + + [[noreturn]] void sys_exit(int status) { -+ sys_libc_log("mlibc: program requested exit"); -+ sys_libc_panic(); ++ syscall(SYSCALL_EXIT, NULL, status); + __builtin_unreachable(); + } + @@ -346,10 +345,10 @@ index 0000000..990eca0 +#endif diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h new file mode 100644 -index 0000000..e23be0d +index 0000000..8a8d77d --- /dev/null +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h -@@ -0,0 +1,36 @@ +@@ -0,0 +1,37 @@ +#ifndef _SYSCALL_H_INCLUDE +#define _SYSCALL_H_INCLUDE + @@ -366,6 +365,7 @@ index 0000000..e23be0d +#define SYSCALL_FSTATAT 10 +#define SYSCALL_FORK 11 +#define SYSCALL_EXECVE 12 ++#define SYSCALL_EXIT 13 + +#include +#include