diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-05-02 21:02:03 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-05-21 14:39:11 -0400 |
commit | 6b5c8045ecc7e726cdaa2a9d9c8e5008050e1252 (patch) | |
tree | 2bf168797818da579310adcd192765fcbe34ae87 /arch/arm/kernel/signal.c | |
parent | 21c1176a72bd019d513b26e05d491a31b50b18d2 (diff) |
arm: new way of handling ERESTART_RESTARTBLOCK
new "syscall start" flag; handled in syscall_trace() by switching
syscall number to that of syscall_restart(2). Restarts of that
kind (ERESTART_RESTARTBLOCK) are handled by setting that bit;
syscall number is not modified until the actual call.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel/signal.c')
-rw-r--r-- | arch/arm/kernel/signal.c | 33 |
1 files changed, 6 insertions, 27 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 6b37d4ddf0b6..75c70d1850df 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -624,12 +624,10 @@ static void do_signal(struct pt_regs *regs, int syscall) | |||
624 | case -ERESTARTNOHAND: | 624 | case -ERESTARTNOHAND: |
625 | case -ERESTARTSYS: | 625 | case -ERESTARTSYS: |
626 | case -ERESTARTNOINTR: | 626 | case -ERESTARTNOINTR: |
627 | case -ERESTART_RESTARTBLOCK: | ||
627 | regs->ARM_r0 = regs->ARM_ORIG_r0; | 628 | regs->ARM_r0 = regs->ARM_ORIG_r0; |
628 | regs->ARM_pc = restart_addr; | 629 | regs->ARM_pc = restart_addr; |
629 | break; | 630 | break; |
630 | case -ERESTART_RESTARTBLOCK: | ||
631 | regs->ARM_r0 = -EINTR; | ||
632 | break; | ||
633 | } | 631 | } |
634 | } | 632 | } |
635 | 633 | ||
@@ -647,12 +645,14 @@ static void do_signal(struct pt_regs *regs, int syscall) | |||
647 | * debugger has chosen to restart at a different PC. | 645 | * debugger has chosen to restart at a different PC. |
648 | */ | 646 | */ |
649 | if (regs->ARM_pc == restart_addr) { | 647 | if (regs->ARM_pc == restart_addr) { |
650 | if (retval == -ERESTARTNOHAND | 648 | if (retval == -ERESTARTNOHAND || |
649 | retval == -ERESTART_RESTARTBLOCK | ||
651 | || (retval == -ERESTARTSYS | 650 | || (retval == -ERESTARTSYS |
652 | && !(ka.sa.sa_flags & SA_RESTART))) { | 651 | && !(ka.sa.sa_flags & SA_RESTART))) { |
653 | regs->ARM_r0 = -EINTR; | 652 | regs->ARM_r0 = -EINTR; |
654 | regs->ARM_pc = continue_addr; | 653 | regs->ARM_pc = continue_addr; |
655 | } | 654 | } |
655 | clear_thread_flag(TIF_SYSCALL_RESTARTSYS); | ||
656 | } | 656 | } |
657 | 657 | ||
658 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 658 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
@@ -679,29 +679,8 @@ static void do_signal(struct pt_regs *regs, int syscall) | |||
679 | * ignore the restart. | 679 | * ignore the restart. |
680 | */ | 680 | */ |
681 | if (retval == -ERESTART_RESTARTBLOCK | 681 | if (retval == -ERESTART_RESTARTBLOCK |
682 | && regs->ARM_pc == continue_addr) { | 682 | && regs->ARM_pc == restart_addr) |
683 | if (thumb_mode(regs)) { | 683 | set_thread_flag(TIF_SYSCALL_RESTARTSYS); |
684 | regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; | ||
685 | regs->ARM_pc -= 2; | ||
686 | } else { | ||
687 | #if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) | ||
688 | regs->ARM_r7 = __NR_restart_syscall; | ||
689 | regs->ARM_pc -= 4; | ||
690 | #else | ||
691 | u32 __user *usp; | ||
692 | |||
693 | regs->ARM_sp -= 4; | ||
694 | usp = (u32 __user *)regs->ARM_sp; | ||
695 | |||
696 | if (put_user(regs->ARM_pc, usp) == 0) { | ||
697 | regs->ARM_pc = KERN_RESTART_CODE; | ||
698 | } else { | ||
699 | regs->ARM_sp += 4; | ||
700 | force_sigsegv(0, current); | ||
701 | } | ||
702 | #endif | ||
703 | } | ||
704 | } | ||
705 | } | 684 | } |
706 | 685 | ||
707 | /* If there's no signal to deliver, we just put the saved sigmask | 686 | /* If there's no signal to deliver, we just put the saved sigmask |