From 19fa391d4fb0e0d3db7cf6b3b85dde18fdf08647 Mon Sep 17 00:00:00 2001 From: Masamichi Takagi Date: Sat, 6 Sep 2014 21:37:59 +0900 Subject: [PATCH] Implement vfork system call It's implemented by making it issue clone system call internally with the arguments of (SIGCHLD, 0, 0, 0, 0). The feature in which the caller of vfork blocks until the child issues exit/execve is not implemented. Refer to #233. --- arch/x86/kernel/include/syscall_list.h | 1 + kernel/syscall.c | 49 +++++++++++++++++--------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/arch/x86/kernel/include/syscall_list.h b/arch/x86/kernel/include/syscall_list.h index b0775db2..adc3a94e 100644 --- a/arch/x86/kernel/include/syscall_list.h +++ b/arch/x86/kernel/include/syscall_list.h @@ -46,6 +46,7 @@ SYSCALL_HANDLED(34, pause) SYSCALL_HANDLED(39, getpid) SYSCALL_HANDLED(56, clone) SYSCALL_DELEGATED(57, fork) +SYSCALL_HANDLED(58, vfork) SYSCALL_HANDLED(59, execve) SYSCALL_HANDLED(60, exit) SYSCALL_HANDLED(61, wait4) diff --git a/kernel/syscall.c b/kernel/syscall.c index 380ce972..89cb7aaf 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1323,26 +1323,29 @@ SYSCALL_DECLARE(execve) return 0; } -SYSCALL_DECLARE(clone) +unsigned long do_fork(int clone_flags, unsigned long newsp, + unsigned long parent_tidptr, unsigned long child_tidptr, + unsigned long tlsblock_base, unsigned long curpc, + unsigned long cursp) { int cpuid; - int clone_flags = ihk_mc_syscall_arg0(ctx); struct process *new; ihk_mc_user_context_t ctx1; struct syscall_request request1 IHK_DMA_ALIGN; - dkprintf("clone(): stack_pointr passed in: 0x%lX, stack pointer of caller: 0x%lx\n", - (unsigned long)ihk_mc_syscall_arg1(ctx), - (unsigned long)ihk_mc_syscall_sp(ctx)); + dkprintf("do_fork,flags=%08x,newsp=%lx,ptidptr=%lx,ctidptr=%lx,tls=%lx,curpc=%lx,cursp=%lx", + clone_flags, newsp, parent_tidptr, child_tidptr, tlsblock_base, curpc, cursp); + + dkprintf("do_fork(): stack_pointr passed in: 0x%lX, stack pointer of caller: 0x%lx\n", + newsp, cursp); cpuid = obtain_clone_cpuid(); if (cpuid == -1) { return -EAGAIN; } - new = clone_process(cpu_local_var(current), ihk_mc_syscall_pc(ctx), - ihk_mc_syscall_arg1(ctx) ? ihk_mc_syscall_arg1(ctx) : - ihk_mc_syscall_sp(ctx), + new = clone_process(cpu_local_var(current), curpc, + newsp ? newsp : cursp, clone_flags); if (!new) { @@ -1395,25 +1398,25 @@ SYSCALL_DECLARE(clone) if (clone_flags & CLONE_PARENT_SETTID) { dkprintf("clone_flags & CLONE_PARENT_SETTID: 0x%lX\n", - (unsigned long)ihk_mc_syscall_arg2(ctx)); + parent_tidptr); - *(int*)ihk_mc_syscall_arg2(ctx) = new->pid; + *(int*)parent_tidptr = new->pid; } if (clone_flags & CLONE_CHILD_CLEARTID) { dkprintf("clone_flags & CLONE_CHILD_CLEARTID: 0x%lX\n", - (unsigned long)ihk_mc_syscall_arg3(ctx)); + child_tidptr); - new->thread.clear_child_tid = (int*)ihk_mc_syscall_arg3(ctx); + new->thread.clear_child_tid = (int*)child_tidptr; } if (clone_flags & CLONE_CHILD_SETTID) { unsigned long phys; dkprintf("clone_flags & CLONE_CHILD_SETTID: 0x%lX\n", - (unsigned long)ihk_mc_syscall_arg3(ctx)); + child_tiptr); if (ihk_mc_pt_virt_to_phys(new->vm->page_table, - (void *)ihk_mc_syscall_arg3(ctx), &phys)) { + (void *)child_tidptr, &phys)) { kprintf("ERROR: looking up physical addr for child process\n"); return -EFAULT; } @@ -1423,10 +1426,9 @@ SYSCALL_DECLARE(clone) if (clone_flags & CLONE_SETTLS) { dkprintf("clone_flags & CLONE_SETTLS: 0x%lX\n", - (unsigned long)ihk_mc_syscall_arg4(ctx)); + tlsblock_base); - new->thread.tlsblock_base = - (unsigned long)ihk_mc_syscall_arg4(ctx); + new->thread.tlsblock_base = tlsblock_base; } else { new->thread.tlsblock_base = @@ -1441,6 +1443,19 @@ SYSCALL_DECLARE(clone) return new->tid; } +SYSCALL_DECLARE(vfork) +{ + return do_fork(SIGCHLD, 0, 0, 0, 0, ihk_mc_syscall_pc(ctx), ihk_mc_syscall_sp(ctx)); +} + +SYSCALL_DECLARE(clone) +{ + return do_fork((int)ihk_mc_syscall_arg0(ctx), ihk_mc_syscall_arg1(ctx), + ihk_mc_syscall_arg2(ctx), ihk_mc_syscall_arg3(ctx), + ihk_mc_syscall_arg4(ctx), ihk_mc_syscall_pc(ctx), + ihk_mc_syscall_sp(ctx)); +} + SYSCALL_DECLARE(set_tid_address) { cpu_local_var(current)->thread.clear_child_tid =