]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
arm: pull all work_pending logics into C function
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 2 Jun 2012 03:58:57 +0000 (23:58 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 21 Jun 2012 04:02:53 +0000 (08:02 +0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/arm/kernel/entry-common.S
arch/arm/kernel/signal.c

index 4afed88d250a6f6127a8a42a7a3462394b078bfc..fbee93f536e987b116ab26432dcca3fa40801bd8 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 fd2392a17ac1befb3464b5a0e77960a0f862b4ca..8756e5dcd377d1d1b14712d64e8c7fbc51cf77a2 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);
 }