diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index 1ea29b7f263c..026a0b21b8f0 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -280,44 +280,15 @@ _syscall_exit_work: .type _work_pending,@function _work_pending: - addoq +TI_flags, $r0, $acr - move.d [$acr], $r10 - btstq TIF_NEED_RESCHED, $r10 ; Need resched? - bpl _work_notifysig ; No, must be signal/notify. - nop - .size _work_pending, . - _work_pending - - .type _work_resched,@function -_work_resched: - move.d $r9, $r1 ; Preserve R9. - jsr schedule - nop - move.d $r1, $r9 - di - - addoq +TI_flags, $r0, $acr - move.d [$acr], $r1 - and.d _TIF_WORK_MASK, $r1 ; Ignore sycall trace counter. - beq _Rexit - nop - btstq TIF_NEED_RESCHED, $r1 - bmi _work_resched ; current->work.need_resched. - nop - .size _work_resched, . - _work_resched - - .type _work_notifysig,@function -_work_notifysig: - ;; Deal with pending signals and notify-resume requests. - addoq +TI_flags, $r0, $acr move.d [$acr], $r12 ; The thread_info_flags parameter. move.d $sp, $r11 ; The regs param. - jsr do_notify_resume - move.d $r9, $r10 ; do_notify_resume syscall/irq param. + jsr do_work_pending + move.d $r9, $r10 ; The syscall/irq param. ba _Rexit nop - .size _work_notifysig, . - _work_notifysig + .size _work_pending, . - _work_pending ;; We get here as a sidetrack when we've entered a syscall with the ;; trace-bit set. We need to call do_syscall_trace and then continue diff --git a/arch/cris/kernel/ptrace.c b/arch/cris/kernel/ptrace.c index 58d44ee1a71f..fd3427e563c5 100644 --- a/arch/cris/kernel/ptrace.c +++ b/arch/cris/kernel/ptrace.c @@ -42,3 +42,26 @@ void do_notify_resume(int canrestart, struct pt_regs *regs, tracehook_notify_resume(regs); } } + +void do_work_pending(int syscall, struct pt_regs *regs, + unsigned int thread_flags) +{ + 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(syscall, regs); + 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); +}