ARM: 7472/1: pull all work_pending logics into C function
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 19 Jul 2012 16:47:55 +0000 (17:47 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sat, 28 Jul 2012 10:11:52 +0000 (11:11 +0100)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/kernel/entry-common.S
arch/arm/kernel/signal.c

index 49d9f93..1873f65 100644 (file)
@@ -51,23 +51,10 @@ ret_fast_syscall:
 fast_work_pending:
        str     r0, [sp, #S_R0+S_OFF]!          @ returned r0
 work_pending:
-       tst     r1, #_TIF_NEED_RESCHED
-       bne     work_resched
-       /*
-        * TIF_SIGPENDING or TIF_NOTIFY_RESUME must've been set if we got here
-        */
-       ldr     r2, [sp, #S_PSR]
        mov     r0, sp                          @ 'regs'
-       tst     r2, #15                         @ are we returning to user mode?
-       bne     no_work_pending                 @ no?  just leave, then...
        mov     r2, why                         @ 'syscall'
-       tst     r1, #_TIF_SIGPENDING            @ delivering a signal?
-       movne   why, #0                         @ prevent further restarts
-       bl      do_notify_resume
-       b       ret_slow_syscall                @ Check work again
-
-work_resched:
-       bl      schedule
+       bl      do_work_pending
+       b       no_work_pending
 /*
  * "slow" syscall return path.  "why" tells us if this was a real syscall.
  */
index fd2392a..8756e5d 100644 (file)
@@ -640,13 +640,24 @@ static void do_signal(struct pt_regs *regs, int syscall)
 }
 
 asmlinkage void
-do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
+do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 {
-       if (thread_flags & _TIF_SIGPENDING)
-               do_signal(regs, syscall);
-
-       if (thread_flags & _TIF_NOTIFY_RESUME) {
-               clear_thread_flag(TIF_NOTIFY_RESUME);
-               tracehook_notify_resume(regs);
-       }
+       do {
+               if (likely(thread_flags & _TIF_NEED_RESCHED)) {
+                       schedule();
+               } else {
+                       if (unlikely(!user_mode(regs)))
+                               return;
+                       local_irq_enable();
+                       if (thread_flags & _TIF_SIGPENDING) {
+                               do_signal(regs, syscall);
+                               syscall = 0;
+                       } else {
+                               clear_thread_flag(TIF_NOTIFY_RESUME);
+                               tracehook_notify_resume(regs);
+                       }
+               }
+               local_irq_disable();
+               thread_flags = current_thread_info()->flags;
+       } while (thread_flags & _TIF_WORK_MASK);
 }