From: Stephen Rothwell Date: Fri, 6 Jul 2012 00:34:02 +0000 (+1000) Subject: Revert "arm: deal with handlerless restarts without leaving the kernel" X-Git-Tag: next-20120724~4^2~1 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=42148731e0a6fa44ce94b493f5dfeefe9dec63ac;p=karo-tx-linux.git Revert "arm: deal with handlerless restarts without leaving the kernel" This reverts commit 9c802c169f964830496be6480ab71d2123cf38a7. Requested by Russell King. --- diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 0e647da6a792..fbee93f536e9 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -54,12 +54,7 @@ work_pending: mov r0, sp @ 'regs' mov r2, why @ 'syscall' bl do_work_pending - tst r0, #1 - beq no_work_pending - mov r0, sp @ pointer to regs - ldmia r0, {r0 - r5} @ have to reload r0 - r5 - b local_restart @ ... and off we go - + b no_work_pending /* * "slow" syscall return path. "why" tells us if this was a real syscall. */ @@ -407,7 +402,6 @@ ENTRY(vector_swi) eor scno, scno, #__NR_SYSCALL_BASE @ check OS number #endif -local_restart: ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing stmdb sp!, {r4, r5} @ push fifth and sixth args diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index c4368c67b042..c0adc5e123be 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -568,13 +568,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ -static int do_signal(struct pt_regs *regs, int syscall) +static void do_signal(struct pt_regs *regs, int syscall) { unsigned int retval = 0, continue_addr = 0, restart_addr = 0; struct k_sigaction ka; siginfo_t info; int signr; - int restart = 0; /* * If we were from a system call, check for system call restarting... @@ -589,12 +588,10 @@ static int do_signal(struct pt_regs *regs, int syscall) * debugger will see the already changed PSW. */ switch (retval) { - case -ERESTART_RESTARTBLOCK: - restart++; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: - restart++; + case -ERESTART_RESTARTBLOCK: regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; @@ -606,15 +603,13 @@ static int do_signal(struct pt_regs *regs, int syscall) * point the debugger may change all our registers ... */ signr = get_signal_to_deliver(&info, &ka, regs, NULL); - /* - * Depending on the signal settings we may need to revert the - * decision to restart the system call. But skip this if a - * debugger has chosen to restart at a different PC. - */ - if (regs->ARM_pc != restart_addr) - restart = 0; if (signr > 0) { - if (unlikely(restart)) { + /* + * Depending on the signal settings we may need to revert the + * decision to restart the system call. But skip this if a + * debugger has chosen to restart at a different PC. + */ + if (regs->ARM_pc == restart_addr) { if (retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS @@ -622,23 +617,28 @@ static int do_signal(struct pt_regs *regs, int syscall) regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } + clear_thread_flag(TIF_SYSCALL_RESTARTSYS); } handle_signal(signr, &ka, &info, regs); - return 0; + return; } - if (unlikely(restart)) { - if (restart > 1) + if (syscall) { + /* + * Handle restarting a different system call. As above, + * if a debugger has chosen to restart at a different PC, + * ignore the restart. + */ + if (retval == -ERESTART_RESTARTBLOCK + && regs->ARM_pc == restart_addr) set_thread_flag(TIF_SYSCALL_RESTARTSYS); - regs->ARM_pc = continue_addr; } restore_saved_sigmask(); - return restart; } -asmlinkage int +asmlinkage void do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) { do { @@ -646,17 +646,10 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) schedule(); } else { if (unlikely(!user_mode(regs))) - return 0; + return; local_irq_enable(); if (thread_flags & _TIF_SIGPENDING) { - if (unlikely(do_signal(regs, syscall))) { - /* - * Restart without handlers. - * Deal with it without leaving - * the kernel space. - */ - return 1; - } + do_signal(regs, syscall); syscall = 0; } else { clear_thread_flag(TIF_NOTIFY_RESUME); @@ -666,5 +659,4 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) local_irq_disable(); thread_flags = current_thread_info()->flags; } while (thread_flags & _TIF_WORK_MASK); - return 0; }