From 76fa7de8e86616f2c9a81f33406afa1d2ebefa43 Mon Sep 17 00:00:00 2001 From: Mark Date: Mon, 4 Nov 2019 13:40:15 +0200 Subject: [PATCH] Clean up sys_fork() a bit --- sys/amd64/sys/thread.c | 81 ++++++++++++++++++++++++++++++++++++++++-- sys/amd64/syscall.c | 71 ------------------------------------ 2 files changed, 79 insertions(+), 73 deletions(-) diff --git a/sys/amd64/sys/thread.c b/sys/amd64/sys/thread.c index 2b95504..11bb7cb 100644 --- a/sys/amd64/sys/thread.c +++ b/sys/amd64/sys/thread.c @@ -1,13 +1,21 @@ #include "sys/amd64/mm/mm.h" +#include "sys/amd64/mm/pool.h" #include "sys/amd64/cpu.h" #include "sys/assert.h" #include "sys/thread.h" #include "sys/string.h" #include "sys/heap.h" #include "sys/vmalloc.h" +#include "sys/errno.h" +#include "sys/fs/vfs.h" +#include "sys/fcntl.h" +#include "sys/sched.h" +#include "sys/tty.h" #include "sys/debug.h" #include "sys/mm.h" +#define THREAD_KSTACK_SIZE 32768 + int thread_init( struct thread *t, mm_space_t space, @@ -19,11 +27,11 @@ int thread_init( uint32_t flags, void *arg) { if (!rsp0_base) { - void *kstack = kmalloc(32768); + void *kstack = kmalloc(THREAD_KSTACK_SIZE); _assert(kstack); rsp0_base = (uintptr_t) kstack; - rsp0_size = 32768; + rsp0_size = THREAD_KSTACK_SIZE; } if (!(flags & THREAD_KERNEL) && !rsp3_base) { @@ -100,6 +108,75 @@ int thread_init( return 0; } +int sys_fork(void) { + asm volatile ("cli"); + int res; + struct thread *thr_src = get_cpu()->thread; + _assert(thr_src); + + struct thread *thr_dst = (struct thread *) kmalloc(sizeof(struct thread)); + if (!thr_dst) { + return -ENOMEM; + } + + // Clone memory space + mm_space_t thread_space = amd64_mm_pool_alloc(); + if (!thread_space) { + kfree(thr_dst); + return -ENOMEM; + } + + if ((res = mm_space_fork(thread_space, thr_src->space, MM_CLONE_FLG_USER | MM_CLONE_FLG_KERNEL)) < 0) { + kfree(thr_dst); + amd64_mm_pool_free(thread_space); + return res; + } + + // Clone process state + void *dst_kstack = kmalloc(THREAD_KSTACK_SIZE); + struct amd64_thread *dst_data = &thr_dst->data; + _assert(dst_kstack); + + dst_data->stack0_base = (uintptr_t) dst_kstack; + dst_data->stack0_size = THREAD_KSTACK_SIZE; + dst_data->stack3_base = thr_src->data.stack3_base; + dst_data->stack3_size = thr_src->data.stack3_size; + dst_data->rsp0 = dst_data->stack0_base + dst_data->stack0_size - sizeof(struct cpu_context); + + // Clone cpu context + struct cpu_context *src_ctx = (struct cpu_context *) thr_src->data.rsp0; + struct cpu_context *dst_ctx = (struct cpu_context *) thr_dst->data.rsp0; + + memcpy(dst_ctx, src_ctx, sizeof(struct cpu_context)); + dst_ctx->cr3 = MM_PHYS(thread_space); + // Return with zero from fork() + dst_ctx->rax = 0; + + // Finish up + thr_dst->space = thread_space; + thr_dst->flags = thr_src->flags; + thr_dst->next = NULL; + + // TODO: clone FDs + memset(&thr_dst->ioctx, 0, sizeof(thr_dst->ioctx)); + memset(thr_dst->fds, 0, sizeof(thr_dst->fds)); + + thr_dst->fds[0].flags = O_RDONLY; + thr_dst->fds[0].vnode = tty0; + thr_dst->fds[0].pos = 0; + + thr_dst->fds[1].flags = O_WRONLY; + thr_dst->fds[1].vnode = tty0; + thr_dst->fds[1].pos = 0; + + sched_add(thr_dst); + + // Parent fork() returns with PID + src_ctx->rax = thr_dst->pid; + + return 0; +} + void amd64_thread_set_ip(struct thread *t, uintptr_t ip) { struct cpu_context *ctx = (struct cpu_context *) t->data.rsp0; diff --git a/sys/amd64/syscall.c b/sys/amd64/syscall.c index d81b65d..36d2909 100644 --- a/sys/amd64/syscall.c +++ b/sys/amd64/syscall.c @@ -10,10 +10,7 @@ #include "sys/fcntl.h" #include "sys/tty.h" #include "sys/amd64/mm/phys.h" -#include "sys/amd64/mm/pool.h" #include "sys/amd64/mm/map.h" -#include "sys/sched.h" -#include "sys/heap.h" static ssize_t sys_read(int fd, void *buf, size_t lim); static ssize_t sys_write(int fd, const void *buf, size_t lim); @@ -184,74 +181,6 @@ static int sys_brk(void *addr) { return 0; } -int sys_fork(void) { - asm volatile ("cli"); - int res; - struct thread *thr_src = get_cpu()->thread; - _assert(thr_src); - - struct thread *thr_dst = (struct thread *) kmalloc(sizeof(struct thread)); - if (!thr_dst) { - return -ENOMEM; - } - - // Clone memory space - mm_space_t thread_space = amd64_mm_pool_alloc(); - if (!thread_space) { - kfree(thr_dst); - return -ENOMEM; - } - - if ((res = mm_space_fork(thread_space, thr_src->space, MM_CLONE_FLG_USER | MM_CLONE_FLG_KERNEL)) < 0) { - kfree(thr_dst); - amd64_mm_pool_free(thread_space); - return res; - } - - // Clone process state - void *dst_kstack = kmalloc(32768); - struct amd64_thread *dst_data = &thr_dst->data; - _assert(dst_kstack); - - dst_data->stack0_base = (uintptr_t) dst_kstack; - dst_data->stack0_size = 32768; - dst_data->stack3_base = thr_src->data.stack3_base; - dst_data->stack3_size = thr_src->data.stack3_size; - dst_data->rsp0 = dst_data->stack0_base + dst_data->stack0_size - sizeof(struct cpu_context); - - // Clone cpu context - struct cpu_context *src_ctx = (struct cpu_context *) thr_src->data.rsp0; - struct cpu_context *dst_ctx = (struct cpu_context *) thr_dst->data.rsp0; - - memcpy(dst_ctx, src_ctx, sizeof(struct cpu_context)); - dst_ctx->cr3 = MM_PHYS(thread_space); - dst_ctx->rax = 0; - - // Finish up - thr_dst->space = thread_space; - thr_dst->flags = thr_src->flags; - thr_dst->next = NULL; - - // TODO: clone FDs - memset(&thr_dst->ioctx, 0, sizeof(thr_dst->ioctx)); - memset(thr_dst->fds, 0, sizeof(thr_dst->fds)); - - thr_dst->fds[0].flags = O_RDONLY; - thr_dst->fds[0].vnode = tty0; - thr_dst->fds[0].pos = 0; - - thr_dst->fds[1].flags = O_WRONLY; - thr_dst->fds[1].vnode = tty0; - thr_dst->fds[1].pos = 0; - - extern void sched_add_to(int cpu, struct thread *t); - sched_add_to(0, thr_dst); - - src_ctx->rax = thr_dst->pid; - - return 0; -} - static void sys_exit(int status) { struct thread *thr = get_cpu()->thread; _assert(thr);