um: kill thread->forking
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... Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
committed by
Richard Weinberger
parent
f9a38eace4
commit
d2ce4e92fa
@@ -20,14 +20,6 @@ struct mm_struct;
|
|||||||
|
|
||||||
struct thread_struct {
|
struct thread_struct {
|
||||||
struct task_struct *saved_task;
|
struct task_struct *saved_task;
|
||||||
/*
|
|
||||||
* This flag is set to 1 before calling do_fork (and analyzed in
|
|
||||||
* copy_thread) to mark that we are begin called from userspace (fork /
|
|
||||||
* vfork / clone), and reset to 0 after. It is left to 0 when called
|
|
||||||
* from kernelspace (i.e. kernel_thread() or fork_idle(),
|
|
||||||
* as of 2.6.11).
|
|
||||||
*/
|
|
||||||
int forking;
|
|
||||||
struct pt_regs regs;
|
struct pt_regs regs;
|
||||||
int singlestep_syscall;
|
int singlestep_syscall;
|
||||||
void *fault_addr;
|
void *fault_addr;
|
||||||
@@ -58,7 +50,6 @@ struct thread_struct {
|
|||||||
|
|
||||||
#define INIT_THREAD \
|
#define INIT_THREAD \
|
||||||
{ \
|
{ \
|
||||||
.forking = 0, \
|
|
||||||
.regs = EMPTY_REGS, \
|
.regs = EMPTY_REGS, \
|
||||||
.fault_addr = NULL, \
|
.fault_addr = NULL, \
|
||||||
.prev_sched = NULL, \
|
.prev_sched = NULL, \
|
||||||
|
@@ -181,11 +181,12 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
void (*handler)(void);
|
void (*handler)(void);
|
||||||
|
int kthread = current->flags & PF_KTHREAD;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
p->thread = (struct thread_struct) INIT_THREAD;
|
p->thread = (struct thread_struct) INIT_THREAD;
|
||||||
|
|
||||||
if (current->thread.forking) {
|
if (!kthread) {
|
||||||
memcpy(&p->thread.regs.regs, ®s->regs,
|
memcpy(&p->thread.regs.regs, ®s->regs,
|
||||||
sizeof(p->thread.regs.regs));
|
sizeof(p->thread.regs.regs));
|
||||||
PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);
|
PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);
|
||||||
@@ -195,8 +196,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
|
|||||||
handler = fork_handler;
|
handler = fork_handler;
|
||||||
|
|
||||||
arch_copy_thread(¤t->thread.arch, &p->thread.arch);
|
arch_copy_thread(¤t->thread.arch, &p->thread.arch);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp);
|
get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp);
|
||||||
p->thread.request.u.thread = current->thread.request.u.thread;
|
p->thread.request.u.thread = current->thread.request.u.thread;
|
||||||
handler = new_thread_handler;
|
handler = new_thread_handler;
|
||||||
@@ -204,7 +204,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
|
|||||||
|
|
||||||
new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
|
new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
|
||||||
|
|
||||||
if (current->thread.forking) {
|
if (!kthread) {
|
||||||
clear_flushed_tls(p);
|
clear_flushed_tls(p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -17,25 +17,25 @@
|
|||||||
|
|
||||||
long sys_fork(void)
|
long sys_fork(void)
|
||||||
{
|
{
|
||||||
long ret;
|
return do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs),
|
||||||
|
|
||||||
current->thread.forking = 1;
|
|
||||||
ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs),
|
|
||||||
¤t->thread.regs, 0, NULL, NULL);
|
¤t->thread.regs, 0, NULL, NULL);
|
||||||
current->thread.forking = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long sys_vfork(void)
|
long sys_vfork(void)
|
||||||
{
|
{
|
||||||
long ret;
|
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
|
||||||
|
|
||||||
current->thread.forking = 1;
|
|
||||||
ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
|
|
||||||
UPT_SP(¤t->thread.regs.regs),
|
UPT_SP(¤t->thread.regs.regs),
|
||||||
¤t->thread.regs, 0, NULL, NULL);
|
¤t->thread.regs, 0, NULL, NULL);
|
||||||
current->thread.forking = 0;
|
}
|
||||||
return ret;
|
|
||||||
|
long sys_clone(unsigned long clone_flags, unsigned long newsp,
|
||||||
|
void __user *parent_tid, void __user *child_tid)
|
||||||
|
{
|
||||||
|
if (!newsp)
|
||||||
|
newsp = UPT_SP(¤t->thread.regs.regs);
|
||||||
|
|
||||||
|
return do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid,
|
||||||
|
child_tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
long old_mmap(unsigned long addr, unsigned long len,
|
long old_mmap(unsigned long addr, unsigned long len,
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
|
extern long sys_clone(unsigned long clone_flags, unsigned long newsp,
|
||||||
|
void __user *parent_tid, void __user *child_tid);
|
||||||
#ifdef __i386__
|
#ifdef __i386__
|
||||||
#include "syscalls_32.h"
|
#include "syscalls_32.h"
|
||||||
#else
|
#else
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
#define ptregs_execve sys_execve
|
#define ptregs_execve sys_execve
|
||||||
#define ptregs_iopl sys_iopl
|
#define ptregs_iopl sys_iopl
|
||||||
#define ptregs_vm86old sys_vm86old
|
#define ptregs_vm86old sys_vm86old
|
||||||
#define ptregs_clone sys_clone
|
#define ptregs_clone i386_clone
|
||||||
#define ptregs_vm86 sys_vm86
|
#define ptregs_vm86 sys_vm86
|
||||||
#define ptregs_sigaltstack sys_sigaltstack
|
#define ptregs_sigaltstack sys_sigaltstack
|
||||||
#define ptregs_vfork sys_vfork
|
#define ptregs_vfork sys_vfork
|
||||||
|
@@ -3,37 +3,24 @@
|
|||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/sched.h"
|
#include <linux/syscalls.h>
|
||||||
#include "linux/shm.h"
|
#include <sysdep/syscalls.h>
|
||||||
#include "linux/ipc.h"
|
|
||||||
#include "linux/syscalls.h"
|
|
||||||
#include "asm/mman.h"
|
|
||||||
#include "asm/uaccess.h"
|
|
||||||
#include "asm/unistd.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The prototype on i386 is:
|
* The prototype on i386 is:
|
||||||
*
|
*
|
||||||
* int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
|
* int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls
|
||||||
*
|
*
|
||||||
* and the "newtls" arg. on i386 is read by copy_thread directly from the
|
* and the "newtls" arg. on i386 is read by copy_thread directly from the
|
||||||
* register saved on the stack.
|
* register saved on the stack.
|
||||||
*/
|
*/
|
||||||
long sys_clone(unsigned long clone_flags, unsigned long newsp,
|
long i386_clone(unsigned long clone_flags, unsigned long newsp,
|
||||||
int __user *parent_tid, void *newtls, int __user *child_tid)
|
int __user *parent_tid, void *newtls, int __user *child_tid)
|
||||||
{
|
{
|
||||||
long ret;
|
return sys_clone(clone_flags, newsp, parent_tid, child_tid);
|
||||||
|
|
||||||
if (!newsp)
|
|
||||||
newsp = UPT_SP(¤t->thread.regs.regs);
|
|
||||||
|
|
||||||
current->thread.forking = 1;
|
|
||||||
ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid,
|
|
||||||
child_tid);
|
|
||||||
current->thread.forking = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
long sys_sigaction(int sig, const struct old_sigaction __user *act,
|
long sys_sigaction(int sig, const struct old_sigaction __user *act,
|
||||||
struct old_sigaction __user *oact)
|
struct old_sigaction __user *oact)
|
||||||
{
|
{
|
||||||
|
@@ -5,12 +5,9 @@
|
|||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "linux/linkage.h"
|
#include <linux/sched.h>
|
||||||
#include "linux/personality.h"
|
#include <asm/prctl.h> /* XXX This should get the constants from libc */
|
||||||
#include "linux/utsname.h"
|
#include <os.h>
|
||||||
#include "asm/prctl.h" /* XXX This should get the constants from libc */
|
|
||||||
#include "asm/uaccess.h"
|
|
||||||
#include "os.h"
|
|
||||||
|
|
||||||
long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
|
long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
|
||||||
{
|
{
|
||||||
@@ -79,20 +76,6 @@ long sys_arch_prctl(int code, unsigned long addr)
|
|||||||
return arch_prctl(current, code, (unsigned long __user *) addr);
|
return arch_prctl(current, code, (unsigned long __user *) addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
long sys_clone(unsigned long clone_flags, unsigned long newsp,
|
|
||||||
void __user *parent_tid, void __user *child_tid)
|
|
||||||
{
|
|
||||||
long ret;
|
|
||||||
|
|
||||||
if (!newsp)
|
|
||||||
newsp = UPT_SP(¤t->thread.regs.regs);
|
|
||||||
current->thread.forking = 1;
|
|
||||||
ret = do_fork(clone_flags, newsp, ¤t->thread.regs, 0, parent_tid,
|
|
||||||
child_tid);
|
|
||||||
current->thread.forking = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void arch_switch_to(struct task_struct *to)
|
void arch_switch_to(struct task_struct *to)
|
||||||
{
|
{
|
||||||
if ((to->thread.arch.fs == 0) || (to->mm == NULL))
|
if ((to->thread.arch.fs == 0) || (to->mm == NULL))
|
||||||
|
Reference in New Issue
Block a user