From ff0ab8af9c3f36e7b6f716c3b9e8811a4202eec6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 5 Oct 2012 18:55:57 -0400 Subject: parisc: optimizations in copy_thread() and friends * in user thread case the registers had been copied as part of task_struct already; no need to do it in copy_thread(). * no need to store kernel stack pointer into regs->r21; we know its offset anyway. * no need to clobber r3 in sys_fork_wrapper and friends - r28 will do just as well and *it* will be overwritten anyway. * no need to mess with storing the return address for child - it should just use syscall_exit. * no need to bother with separate stack frame for sys_clone() - just branch there and be done with that. * no need to bother with wrapper_exit - we need it only on the child_return, so let's just do it there. * use the same ksp for kernel threads and userland ones, while we are at it, and let ret_from_kernel_execve() go through the normal syscall_exit. More straightforward is better here... [fixes from jejb folded] Signed-off-by: Al Viro --- arch/parisc/kernel/process.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'arch/parisc/kernel/process.c') diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 44e8534c52e9..38db36f64307 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -253,14 +254,16 @@ copy_thread(unsigned long clone_flags, unsigned long usp, #ifdef CONFIG_HPUX extern void * const hpux_child_return; #endif - - if (unlikely((p->flags & PF_KTHREAD) && usp != 0)) { + if (unlikely(p->flags & PF_KTHREAD)) { memset(cregs, 0, sizeof(struct pt_regs)); + if (!usp) /* idle thread */ + return 0; + /* kernel thread */ - cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN; /* Must exit via ret_from_kernel_thread in order * to call schedule_tail() */ + cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; cregs->kpc = (unsigned long) &ret_from_kernel_thread; /* * Copy function and argument to be called from @@ -275,22 +278,8 @@ copy_thread(unsigned long clone_flags, unsigned long usp, cregs->gr[25] = arg; } else { /* user thread */ - /* - * Note that the fork wrappers are responsible - * for setting gr[21]. - */ - - *cregs = *pregs; - - /* Set the return value for the child. Note that this is not - actually restored by the syscall exit path, but we put it - here for consistency in case of signals. */ - cregs->gr[28] = 0; /* child */ - - /* Use same stack depth as parent */ - cregs->ksp = (unsigned long)stack - + (pregs->gr[21] & (THREAD_SIZE - 1)); cregs->gr[30] = usp; + cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE; if (personality(p->personality) == PER_HPUX) { #ifdef CONFIG_HPUX cregs->kpc = (unsigned long) &hpux_child_return; @@ -302,8 +291,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, } /* Setup thread TLS area from the 4th parameter in clone */ if (clone_flags & CLONE_SETTLS) - cregs->cr27 = pregs->gr[23]; - + cregs->cr27 = pregs->gr[23]; } return 0; -- cgit v1.2.3