]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Revert "arm: deal with handlerless restarts without leaving the kernel"
authorStephen Rothwell <sfr@canb.auug.org.au>
Fri, 6 Jul 2012 00:34:02 +0000 (10:34 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Fri, 6 Jul 2012 00:34:02 +0000 (10:34 +1000)
This reverts commit 9c802c169f964830496be6480ab71d2123cf38a7.

Requested by Russell King.

arch/arm/kernel/entry-common.S
arch/arm/kernel/signal.c

index 0e647da6a7921bd6865951ce97c362695a2099b9..fbee93f536e987b116ab26432dcca3fa40801bd8 100644 (file)
@@ -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
 
index c4368c67b042ecb8416609784d1b28e7f8a9d3ba..c0adc5e123bed1c32be58fb5aa951b3aeae23056 100644 (file)
@@ -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;
 }