we only use that to tell copy_thread() done by syscall from that done by kernel_thread(). However, it's easier to do simply by checking PF_KTHREAD in thread flags. Merge sys_clone() guts for 32bit and 64bit, while we are at it...
Unified · Split
| @@ -20,14 +20,6 @@ struct mm_struct; · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | struct thread_struct { |
| 22 | 22 | struct task_struct *saved_task; |
| 23 | − /* | |
| 24 | − * This flag is set to 1 before calling do_fork (and analyzed in | |
| 25 | − * copy_thread) to mark that we are begin called from userspace (fork / | |
| 26 | − * vfork / clone), and reset to 0 after. It is left to 0 when called | |
| 27 | − * from kernelspace (i.e. kernel_thread() or fork_idle(), | |
| 28 | − * as of 2.6.11). | |
| 29 | − */ | |
| 30 | − int forking; | |
| 31 | 23 | struct pt_regs regs; |
| 32 | 24 | int singlestep_syscall; |
| 33 | 25 | void *fault_addr; |
| @@ -58,7 +50,6 @@ struct thread_struct { · 24 unmodified lines | ||
| 58 | 50 | |
| 59 | 51 | #define INIT_THREAD \ |
| 60 | 52 | { \ |
| 61 | − .forking = 0, \ | |
| 62 | 53 | .regs = EMPTY_REGS, \ |
| 63 | 54 | .fault_addr = NULL, \ |
| 64 | 55 | .prev_sched = NULL, \ |
| @@ -181,11 +181,12 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, · 180 unmodified lines | ||
| 181 | 181 | struct pt_regs *regs) |
| 182 | 182 | { |
| 183 | 183 | void (*handler)(void); |
| 184 | + int kthread = current->flags & PF_KTHREAD; | |
| 184 | 185 | int ret = 0; |
| 185 | 186 | |
| 186 | 187 | p->thread = (struct thread_struct) INIT_THREAD; |
| 187 | 188 | |
| 188 | − if (current->thread.forking) { | |
| 189 | + if (!kthread) { | |
| 189 | 190 | memcpy(&p->thread.regs.regs, ®s->regs, |
| 190 | 191 | sizeof(p->thread.regs.regs)); |
| 191 | 192 | PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); |
| @@ -195,8 +196,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, · 3 unmodified lines | ||
| 195 | 196 | handler = fork_handler; |
| 196 | 197 | |
| 197 | 198 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); |
| 198 | − } | |
| 199 | − else { | |
| 199 | + } else { | |
| 200 | 200 | get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); |
| 201 | 201 | p->thread.request.u.thread = current->thread.request.u.thread; |
| 202 | 202 | handler = new_thread_handler; |
| @@ -204,7 +204,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, · 1 unmodified line | ||
| 204 | 204 | |
| 205 | 205 | new_thread(task_stack_page(p), &p->thread.switch_buf, handler); |
| 206 | 206 | |
| 207 | − if (current->thread.forking) { | |
| 207 | + if (!kthread) { | |
| 208 | 208 | clear_flushed_tls(p); |
| 209 | 209 | |
| 210 | 210 | /* |
| @@ -17,25 +17,25 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | long sys_fork(void) |
| 19 | 19 | { |
| 20 | − long ret; | |
| 21 | − | |
| 22 | − current->thread.forking = 1; | |
| 23 | − ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), | |
| 20 | + return do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), | |
| 24 | 21 | ¤t->thread.regs, 0, NULL, NULL); |
| 25 | − current->thread.forking = 0; | |
| 26 | − return ret; | |
| 27 | 22 | } |
| 28 | 23 | |
| 29 | 24 | long sys_vfork(void) |
| 30 | 25 | { |
| 31 | − long ret; | |
| 32 | − | |
| 33 | − current->thread.forking = 1; | |
| 34 | − ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, | |
| 26 | + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, | |
| 35 | 27 | UPT_SP(¤t->thread.regs.regs), |
| 36 | 28 | ¤t->thread.regs, 0, NULL, NULL); |
| 37 | − current->thread.forking = 0; | |
| 38 | − return ret; | |
| 29 | +} | |
| 30 | + | |
| 31 | +long sys_clone(unsigned long clone_flags, unsigned long newsp, | |
| 32 | + void __user *parent_tid, void __user *child_tid) | |
| 33 | +{ | |
| 34 | + if (!newsp) | |
| 35 | + newsp = UPT_SP(¤t->thread.regs.regs); | |
| 36 | + | |
| 37 | + return do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, | |
| 38 | + child_tid); | |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | 41 | long old_mmap(unsigned long addr, unsigned long len, |
| @@ -1,3 +1,5 @@ | ||
| 1 | +extern long sys_clone(unsigned long clone_flags, unsigned long newsp, | |
| 2 | + void __user *parent_tid, void __user *child_tid); | |
| 1 | 3 | #ifdef __i386__ |
| 2 | 4 | #include "syscalls_32.h" |
| 3 | 5 | #else |
| @@ -28,7 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | #define ptregs_execve sys_execve |
| 29 | 29 | #define ptregs_iopl sys_iopl |
| 30 | 30 | #define ptregs_vm86old sys_vm86old |
| 31 | −#define ptregs_clone sys_clone | |
| 31 | +#define ptregs_clone i386_clone | |
| 32 | 32 | #define ptregs_vm86 sys_vm86 |
| 33 | 33 | #define ptregs_sigaltstack sys_sigaltstack |
| 34 | 34 | #define ptregs_vfork sys_vfork |
| @@ -3,37 +3,24 @@ · 2 unmodified lines | ||
| 3 | 3 | * Licensed under the GPL |
| 4 | 4 | */ |
| 5 | 5 | |
| 6 | −#include "linux/sched.h" | |
| 7 | −#include "linux/shm.h" | |
| 8 | −#include "linux/ipc.h" | |
| 9 | −#include "linux/syscalls.h" | |
| 10 | −#include "asm/mman.h" | |
| 11 | −#include "asm/uaccess.h" | |
| 12 | −#include "asm/unistd.h" | |
| 6 | +#include <linux/syscalls.h> | |
| 7 | +#include <sysdep/syscalls.h> | |
| 13 | 8 | |
| 14 | 9 | /* |
| 15 | 10 | * The prototype on i386 is: |
| 16 | 11 | * |
| 17 | − * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr) | |
| 12 | + * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls | |
| 18 | 13 | * |
| 19 | 14 | * and the "newtls" arg. on i386 is read by copy_thread directly from the |
| 20 | 15 | * register saved on the stack. |
| 21 | 16 | */ |
| 22 | −long sys_clone(unsigned long clone_flags, unsigned long newsp, | |
| 23 | − int __user *parent_tid, void *newtls, int __user *child_tid) | |
| 17 | +long i386_clone(unsigned long clone_flags, unsigned long newsp, | |
| 18 | + int __user *parent_tid, void *newtls, int __user *child_tid) | |
| 24 | 19 | { |
| 25 | − long ret; | |
| 26 | − | |
| 27 | − if (!newsp) | |
| 28 | − newsp = UPT_SP(¤t->thread.regs.regs); | |
| 29 | − | |
| 30 | − current->thread.forking = 1; | |
| 31 | − ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, | |
| 32 | − child_tid); | |
| 33 | − current->thread.forking = 0; | |
| 34 | − return ret; | |
| 20 | + return sys_clone(clone_flags, newsp, parent_tid, child_tid); | |
| 35 | 21 | } |
| 36 | 22 | |
| 23 | + | |
| 37 | 24 | long sys_sigaction(int sig, const struct old_sigaction __user *act, |
| 38 | 25 | struct old_sigaction __user *oact) |
| 39 | 26 | { |
| @@ -5,12 +5,9 @@ · 4 unmodified lines | ||
| 5 | 5 | * Licensed under the GPL |
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | −#include "linux/linkage.h" | |
| 9 | −#include "linux/personality.h" | |
| 10 | −#include "linux/utsname.h" | |
| 11 | −#include "asm/prctl.h" /* XXX This should get the constants from libc */ | |
| 12 | −#include "asm/uaccess.h" | |
| 13 | −#include "os.h" | |
| 8 | +#include <linux/sched.h> | |
| 9 | +#include <asm/prctl.h> /* XXX This should get the constants from libc */ | |
| 10 | +#include <os.h> | |
| 14 | 11 | |
| 15 | 12 | long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) |
| 16 | 13 | { |
| @@ -79,20 +76,6 @@ long sys_arch_prctl(int code, unsigned long addr) · 62 unmodified lines | ||
| 79 | 76 | return arch_prctl(current, code, (unsigned long __user *) addr); |
| 80 | 77 | } |
| 81 | 78 | |
| 82 | −long sys_clone(unsigned long clone_flags, unsigned long newsp, | |
| 83 | − void __user *parent_tid, void __user *child_tid) | |
| 84 | −{ | |
| 85 | − long ret; | |
| 86 | − | |
| 87 | − if (!newsp) | |
| 88 | − newsp = UPT_SP(¤t->thread.regs.regs); | |
| 89 | − current->thread.forking = 1; | |
| 90 | − ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid, | |
| 91 | − child_tid); | |
| 92 | − current->thread.forking = 0; | |
| 93 | − return ret; | |
| 94 | −} | |
| 95 | − | |
| 96 | 79 | void arch_switch_to(struct task_struct *to) |
| 97 | 80 | { |
| 98 | 81 | if ((to->thread.arch.fs == 0) || (to->mm == NULL)) |