Commit f4205a53 authored by William Lee Irwin III's avatar William Lee Irwin III Committed by Linus Torvalds

[PATCH] sched: consolidate CLONE_IDLETASK masking

Every arch now bears the burden of sanitizing CLONE_IDLETASK out of the
clone_flags passed to do_fork() by userspace.  This patch hoists the
masking of CLONE_IDLETASK out of the system call entrypoints into
do_fork(), and thereby removes some small overheads from do_fork(), as
do_fork() may now assume that CLONE_IDLETASK has been cleared.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent fe92ebf3
...@@ -246,8 +246,7 @@ alpha_clone(unsigned long clone_flags, unsigned long usp, ...@@ -246,8 +246,7 @@ alpha_clone(unsigned long clone_flags, unsigned long usp,
if (!usp) if (!usp)
usp = rdusp(); usp = rdusp();
return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid);
parent_tid, child_tid);
} }
int int
......
...@@ -257,7 +257,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct ...@@ -257,7 +257,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct
if (!newsp) if (!newsp)
newsp = regs->ARM_sp; newsp = regs->ARM_sp;
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
} }
asmlinkage int sys_vfork(struct pt_regs *regs) asmlinkage int sys_vfork(struct pt_regs *regs)
......
...@@ -256,7 +256,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct ...@@ -256,7 +256,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, struct
if (!newsp) if (!newsp)
newsp = regs->ARM_sp; newsp = regs->ARM_sp;
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
} }
asmlinkage int sys_vfork(struct pt_regs *regs) asmlinkage int sys_vfork(struct pt_regs *regs)
......
...@@ -180,7 +180,7 @@ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags, ...@@ -180,7 +180,7 @@ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,
{ {
if (!newusp) if (!newusp)
newusp = rdusp(); newusp = rdusp();
return do_fork(flags & ~CLONE_IDLETASK, newusp, regs, 0, parent_tid, child_tid); return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);
} }
/* vfork is a system call in i386 because of register-pressure - maybe /* vfork is a system call in i386 because of register-pressure - maybe
......
...@@ -189,7 +189,7 @@ asmlinkage int h8300_clone(struct pt_regs *regs) ...@@ -189,7 +189,7 @@ asmlinkage int h8300_clone(struct pt_regs *regs)
newsp = regs->er2; newsp = regs->er2;
if (!newsp) if (!newsp)
newsp = rdusp(); newsp = rdusp();
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
} }
......
...@@ -595,7 +595,7 @@ asmlinkage int sys_clone(struct pt_regs regs) ...@@ -595,7 +595,7 @@ asmlinkage int sys_clone(struct pt_regs regs)
child_tidptr = (int __user *)regs.edi; child_tidptr = (int __user *)regs.edi;
if (!newsp) if (!newsp)
newsp = regs.esp; newsp = regs.esp;
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, parent_tidptr, child_tidptr); return do_fork(clone_flags, newsp, &regs, 0, parent_tidptr, child_tidptr);
} }
/* /*
......
...@@ -41,7 +41,7 @@ ENTRY(ia32_clone) ...@@ -41,7 +41,7 @@ ENTRY(ia32_clone)
zxt4 out1=in1 // newsp zxt4 out1=in1 // newsp
mov out3=16 // stacksize (compensates for 16-byte scratch area) mov out3=16 // stacksize (compensates for 16-byte scratch area)
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK mov out0=in0 // out0 = clone_flags
zxt4 out4=in2 // out4 = parent_tidptr zxt4 out4=in2 // out4 = parent_tidptr
zxt4 out5=in4 // out5 = child_tidptr zxt4 out5=in4 // out5 = child_tidptr
br.call.sptk.many rp=do_fork br.call.sptk.many rp=do_fork
......
...@@ -195,11 +195,6 @@ void foo(void) ...@@ -195,11 +195,6 @@ void foo(void)
DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec)); DEFINE(IA64_TIMESPEC_TV_NSEC_OFFSET, offsetof (struct timespec, tv_nsec));
DEFINE(CLONE_IDLETASK_BIT, 12);
#if CLONE_IDLETASK != (1 << 12)
# error "CLONE_IDLETASK_BIT incorrect, please fix"
#endif
DEFINE(CLONE_SETTLS_BIT, 19); DEFINE(CLONE_SETTLS_BIT, 19);
#if CLONE_SETTLS != (1<<19) #if CLONE_SETTLS != (1<<19)
# error "CLONE_SETTLS_BIT incorrect, please fix" # error "CLONE_SETTLS_BIT incorrect, please fix"
......
...@@ -128,7 +128,7 @@ GLOBAL_ENTRY(sys_clone2) ...@@ -128,7 +128,7 @@ GLOBAL_ENTRY(sys_clone2)
(p6) st8 [r2]=in5 // store TLS in r16 for copy_thread() (p6) st8 [r2]=in5 // store TLS in r16 for copy_thread()
mov out5=in4 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID mov out5=in4 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK mov out0=in0 // out0 = clone_flags
br.call.sptk.many rp=do_fork br.call.sptk.many rp=do_fork
.ret1: .restore sp .ret1: .restore sp
adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
...@@ -157,7 +157,7 @@ GLOBAL_ENTRY(sys_clone) ...@@ -157,7 +157,7 @@ GLOBAL_ENTRY(sys_clone)
(p6) st8 [r2]=in4 // store TLS in r13 (tp) (p6) st8 [r2]=in4 // store TLS in r13 (tp)
mov out5=in3 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID mov out5=in3 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID
adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs adds out2=IA64_SWITCH_STACK_SIZE+16,sp // out2 = &regs
dep out0=0,in0,CLONE_IDLETASK_BIT,1 // out0 = clone_flags & ~CLONE_IDLETASK mov out0=in0 // out0 = clone_flags
br.call.sptk.many rp=do_fork br.call.sptk.many rp=do_fork
.ret2: .restore sp .ret2: .restore sp
adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack
......
...@@ -232,7 +232,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs) ...@@ -232,7 +232,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs)
child_tidptr = (int *)regs->d4; child_tidptr = (int *)regs->d4;
if (!newsp) if (!newsp)
newsp = rdusp(); newsp = rdusp();
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, return do_fork(clone_flags, newsp, regs, 0,
parent_tidptr, child_tidptr); parent_tidptr, child_tidptr);
} }
......
...@@ -188,7 +188,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs) ...@@ -188,7 +188,7 @@ asmlinkage int m68k_clone(struct pt_regs *regs)
newsp = regs->d2; newsp = regs->d2;
if (!newsp) if (!newsp)
newsp = rdusp(); newsp = rdusp();
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL); return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
} }
int copy_thread(int nr, unsigned long clone_flags, int copy_thread(int nr, unsigned long clone_flags,
......
...@@ -180,7 +180,7 @@ static_unused int _sys_clone(nabi_no_regargs struct pt_regs regs) ...@@ -180,7 +180,7 @@ static_unused int _sys_clone(nabi_no_regargs struct pt_regs regs)
newsp = regs.regs[29]; newsp = regs.regs[29];
parent_tidptr = (int *) regs.regs[6]; parent_tidptr = (int *) regs.regs[6];
child_tidptr = (int *) regs.regs[7]; child_tidptr = (int *) regs.regs[7];
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, return do_fork(clone_flags, newsp, &regs, 0,
parent_tidptr, child_tidptr); parent_tidptr, child_tidptr);
} }
......
...@@ -262,7 +262,7 @@ sys_clone(unsigned long clone_flags, unsigned long usp, ...@@ -262,7 +262,7 @@ sys_clone(unsigned long clone_flags, unsigned long usp,
if(usp == 0) if(usp == 0)
usp = regs->gr[30]; usp = regs->gr[30];
return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, user_tid, NULL); return do_fork(clone_flags, usp, regs, 0, user_tid, NULL);
} }
int int
......
...@@ -555,8 +555,7 @@ int sys_clone(unsigned long clone_flags, unsigned long usp, ...@@ -555,8 +555,7 @@ int sys_clone(unsigned long clone_flags, unsigned long usp,
CHECK_FULL_REGS(regs); CHECK_FULL_REGS(regs);
if (usp == 0) if (usp == 0)
usp = regs->gpr[1]; /* stack pointer for child */ usp = regs->gpr[1]; /* stack pointer for child */
return do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);
parent_tidp, child_tidp);
} }
int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6, int sys_fork(int p1, int p2, int p3, int p4, int p5, int p6,
......
...@@ -458,7 +458,7 @@ int sys_clone(unsigned long clone_flags, unsigned long p2, unsigned long p3, ...@@ -458,7 +458,7 @@ int sys_clone(unsigned long clone_flags, unsigned long p2, unsigned long p3,
} }
} }
return do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0, return do_fork(clone_flags, p2, regs, 0,
(int __user *)parent_tidptr, (int __user *)child_tidptr); (int __user *)parent_tidptr, (int __user *)child_tidptr);
} }
......
...@@ -1219,7 +1219,7 @@ asmlinkage long sys32_clone(struct pt_regs regs) ...@@ -1219,7 +1219,7 @@ asmlinkage long sys32_clone(struct pt_regs regs)
child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL); child_tidptr = (int *) (regs.gprs[5] & 0x7fffffffUL);
if (!newsp) if (!newsp)
newsp = regs.gprs[15]; newsp = regs.gprs[15];
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, return do_fork(clone_flags, newsp, &regs, 0,
parent_tidptr, child_tidptr); parent_tidptr, child_tidptr);
} }
......
...@@ -336,7 +336,7 @@ asmlinkage long sys_clone(struct pt_regs regs) ...@@ -336,7 +336,7 @@ asmlinkage long sys_clone(struct pt_regs regs)
child_tidptr = (int __user *) regs.gprs[5]; child_tidptr = (int __user *) regs.gprs[5];
if (!newsp) if (!newsp)
newsp = regs.gprs[15]; newsp = regs.gprs[15];
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, return do_fork(clone_flags, newsp, &regs, 0,
parent_tidptr, child_tidptr); parent_tidptr, child_tidptr);
} }
......
...@@ -440,7 +440,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, ...@@ -440,7 +440,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
{ {
if (!newsp) if (!newsp)
newsp = regs.regs[15]; newsp = regs.regs[15];
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, &regs, 0, return do_fork(clone_flags, newsp, &regs, 0,
(int __user *)parent_tidptr, (int __user *)child_tidptr); (int __user *)parent_tidptr, (int __user *)child_tidptr);
} }
......
...@@ -820,7 +820,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, ...@@ -820,7 +820,7 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
{ {
if (!newsp) if (!newsp)
newsp = pregs->regs[15]; newsp = pregs->regs[15];
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, pregs, 0, 0, 0); return do_fork(clone_flags, newsp, pregs, 0, 0, 0);
} }
/* /*
......
...@@ -435,8 +435,6 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags, ...@@ -435,8 +435,6 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags,
{ {
unsigned long parent_tid_ptr, child_tid_ptr; unsigned long parent_tid_ptr, child_tid_ptr;
clone_flags &= ~CLONE_IDLETASK;
parent_tid_ptr = regs->u_regs[UREG_I2]; parent_tid_ptr = regs->u_regs[UREG_I2];
child_tid_ptr = regs->u_regs[UREG_I4]; child_tid_ptr = regs->u_regs[UREG_I4];
......
...@@ -588,8 +588,6 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags, ...@@ -588,8 +588,6 @@ asmlinkage long sparc_do_fork(unsigned long clone_flags,
{ {
int __user *parent_tid_ptr, *child_tid_ptr; int __user *parent_tid_ptr, *child_tid_ptr;
clone_flags &= ~CLONE_IDLETASK;
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_32BIT)) { if (test_thread_flag(TIF_32BIT)) {
parent_tid_ptr = compat_ptr(regs->u_regs[UREG_I2]); parent_tid_ptr = compat_ptr(regs->u_regs[UREG_I2]);
......
...@@ -1148,8 +1148,7 @@ asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, ...@@ -1148,8 +1148,7 @@ asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
void __user *child_tid = (void __user *)regs->rdi; void __user *child_tid = (void __user *)regs->rdi;
if (!newsp) if (!newsp)
newsp = regs->rsp; newsp = regs->rsp;
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
parent_tid, child_tid);
} }
/* /*
......
...@@ -555,8 +555,7 @@ asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void _ ...@@ -555,8 +555,7 @@ asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp, void _
{ {
if (!newsp) if (!newsp)
newsp = regs->rsp; newsp = regs->rsp;
return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
parent_tid, child_tid);
} }
/* /*
......
...@@ -40,7 +40,6 @@ struct exec_domain; ...@@ -40,7 +40,6 @@ struct exec_domain;
#define CLONE_FS 0x00000200 /* set if fs info shared between processes */ #define CLONE_FS 0x00000200 /* set if fs info shared between processes */
#define CLONE_FILES 0x00000400 /* set if open files shared between processes */ #define CLONE_FILES 0x00000400 /* set if open files shared between processes */
#define CLONE_SIGHAND 0x00000800 /* set if signal handlers and blocked signals shared */ #define CLONE_SIGHAND 0x00000800 /* set if signal handlers and blocked signals shared */
#define CLONE_IDLETASK 0x00001000 /* set if new pid should be 0 (kernel only)*/
#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */ #define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */
#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ #define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */ #define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */
......
...@@ -45,6 +45,9 @@ ...@@ -45,6 +45,9 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
/* set if new pid should be 0 (kernel only)*/
#define CLONE_IDLETASK 0x00001000
/* The idle threads do not count.. /* The idle threads do not count..
* Protected by write_lock_irq(&tasklist_lock) * Protected by write_lock_irq(&tasklist_lock)
*/ */
...@@ -1194,7 +1197,7 @@ task_t * __init fork_idle(int cpu) ...@@ -1194,7 +1197,7 @@ task_t * __init fork_idle(int cpu)
static inline int fork_traceflag (unsigned clone_flags) static inline int fork_traceflag (unsigned clone_flags)
{ {
if (clone_flags & (CLONE_UNTRACED | CLONE_IDLETASK)) if (clone_flags & CLONE_UNTRACED)
return 0; return 0;
else if (clone_flags & CLONE_VFORK) { else if (clone_flags & CLONE_VFORK) {
if (current->ptrace & PT_TRACE_VFORK) if (current->ptrace & PT_TRACE_VFORK)
...@@ -1225,6 +1228,7 @@ long do_fork(unsigned long clone_flags, ...@@ -1225,6 +1228,7 @@ long do_fork(unsigned long clone_flags,
int trace = 0; int trace = 0;
long pid; long pid;
clone_flags &= ~CLONE_IDLETASK;
if (unlikely(current->ptrace)) { if (unlikely(current->ptrace)) {
trace = fork_traceflag (clone_flags); trace = fork_traceflag (clone_flags);
if (trace) if (trace)
...@@ -1254,13 +1258,11 @@ long do_fork(unsigned long clone_flags, ...@@ -1254,13 +1258,11 @@ long do_fork(unsigned long clone_flags,
set_tsk_thread_flag(p, TIF_SIGPENDING); set_tsk_thread_flag(p, TIF_SIGPENDING);
} }
if (likely(!(clone_flags & CLONE_IDLETASK))) {
if (!(clone_flags & CLONE_STOPPED)) if (!(clone_flags & CLONE_STOPPED))
wake_up_new_task(p, clone_flags); wake_up_new_task(p, clone_flags);
else else
p->state = TASK_STOPPED; p->state = TASK_STOPPED;
++total_forks; ++total_forks;
}
if (unlikely (trace)) { if (unlikely (trace)) {
current->ptrace_message = pid; current->ptrace_message = pid;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment