Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758972AbbBHUp3 (ORCPT ); Sun, 8 Feb 2015 15:45:29 -0500 Received: from mail-lb0-f169.google.com ([209.85.217.169]:55994 "EHLO mail-lb0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753377AbbBHUpN (ORCPT ); Sun, 8 Feb 2015 15:45:13 -0500 From: Rabin Vincent To: jesper.nilsson@axis.com Cc: linux-cris-kernel@axis.com, viro@zeniv.linux.org.uk, linux-kernel@vger.kernel.org, Rabin Vincent Subject: [PATCH 3/3] CRISv32: handle multiple signals Date: Sun, 8 Feb 2015 21:45:04 +0100 Message-Id: <1423428304-26586-3-git-send-email-rabin@rab.in> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1423428304-26586-1-git-send-email-rabin@rab.in> References: <1423428304-26586-1-git-send-email-rabin@rab.in> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4086 Lines: 144 Al Viro noted that CRIS fails to handle multiple signals. This fixes the problem for CRISv32 by making it use a C work_pending handling loop similar to the ARM implementation in 0a267fa6a15d41c ("ARM: 7472/1: pull all work_pending logics into C function"). This also happens to fixes the warnings which currently trigger on CRISv32 due to do_signal() being called with interrupts disabled. Test case (should die of the SIGSEGV which gets raised when setting up the stack for SIGALRM, but instead reaches and executes the _exit(1)): #include #include #include #include static void handler(int sig) { } int main(int argc, char *argv[]) { int ret; struct itimerval t1 = { .it_value = {1} }; stack_t ss = { .ss_sp = NULL, .ss_size = SIGSTKSZ, }; struct sigaction action = { .sa_handler = handler, .sa_flags = SA_ONSTACK, }; ret = sigaltstack(&ss, NULL); if (ret < 0) err(1, "sigaltstack"); sigaction(SIGALRM, &action, NULL); setitimer(ITIMER_REAL, &t1, NULL); pause(); _exit(1); return 0; } Reported-by: Al Viro Link: http://lkml.kernel.org/r/20121208074429.GC4939@ZenIV.linux.org.uk Signed-off-by: Rabin Vincent --- arch/cris/arch-v32/kernel/entry.S | 35 +++-------------------------------- arch/cris/kernel/ptrace.c | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index 1ea29b7..026a0b2 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -281,43 +281,14 @@ _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 58d44ee..fd3427e 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); +} -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/