diff --git a/src/arch/x86_64/syscall.asm b/src/arch/x86_64/syscall.asm index f8f05a57..ad33b3de 100644 --- a/src/arch/x86_64/syscall.asm +++ b/src/arch/x86_64/syscall.asm @@ -16,7 +16,8 @@ extern syscall_fstat extern syscall_fork extern syscall_execve extern syscall_waitpid -func_count equ 15 +extern syscall_exit +func_count equ 16 func_table: @@ -35,6 +36,7 @@ func_table: dq syscall_fork dq syscall_execve dq syscall_waitpid + dq syscall_exit section .text global asm_syscall_entry diff --git a/src/sys/syscalls/exit.c b/src/sys/syscalls/exit.c new file mode 100644 index 00000000..c61de29f --- /dev/null +++ b/src/sys/syscalls/exit.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include +#include + +void syscall_exit(int status){ + proc_t* proc = arch_getcls()->thread->proc; + + spinlock_acquire(&proc->lock); + + // TODO make all other threads exit + + free(proc->threads); + + for(uintmax_t fd = 0; fd < proc->fdtable.fdcount; ++ fd) + fd_free(&proc->fdtable, fd); + + + + proc->state = PROC_STATE_ZOMBIE; + proc->status = status; + + vfs_close(proc->root); + vfs_close(proc->cwd); + + proc_t* init = sched_getinit(); + + spinlock_acquire(&init->lock); + + proc_t* child = proc->child; + proc_t* firstchild = child; + + while(child){ + spinlock_acquire(&child->lock); + child->parent = init; + if(!child->sibling){ + child->sibling = init->child; + init->child = firstchild; + } + spinlock_release(&child->lock); + child = child->sibling; + } + + spinlock_release(&init->lock); + spinlock_release(&proc->lock); + + event_signal(&proc->parent->childevent, true); + + sched_dequeue(); + + __builtin_unreachable(); + +}