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) | |
download | linux-6b5c8045ecc7e726cdaa2a9d9c8e5008050e1252.tar.bz2 |
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) case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: + case -ERESTART_RESTARTBLOCK: regs->ARM_r0 = regs->ARM_ORIG_r0; regs->ARM_pc = restart_addr; break; - case -ERESTART_RESTARTBLOCK: - regs->ARM_r0 = -EINTR; - break; } } @@ -647,12 +645,14 @@ static void do_signal(struct pt_regs *regs, int syscall) * debugger has chosen to restart at a different PC. */ if (regs->ARM_pc == restart_addr) { - if (retval == -ERESTARTNOHAND + if (retval == -ERESTARTNOHAND || + retval == -ERESTART_RESTARTBLOCK || (retval == -ERESTARTSYS && !(ka.sa.sa_flags & SA_RESTART))) { regs->ARM_r0 = -EINTR; regs->ARM_pc = continue_addr; } + clear_thread_flag(TIF_SYSCALL_RESTARTSYS); } if (test_thread_flag(TIF_RESTORE_SIGMASK)) @@ -679,29 +679,8 @@ static void do_signal(struct pt_regs *regs, int syscall) * ignore the restart. */ if (retval == -ERESTART_RESTARTBLOCK - && regs->ARM_pc == continue_addr) { - if (thumb_mode(regs)) { - regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE; - regs->ARM_pc -= 2; - } else { -#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT) - regs->ARM_r7 = __NR_restart_syscall; - regs->ARM_pc -= 4; -#else - u32 __user *usp; - - regs->ARM_sp -= 4; - usp = (u32 __user *)regs->ARM_sp; - - if (put_user(regs->ARM_pc, usp) == 0) { - regs->ARM_pc = KERN_RESTART_CODE; - } else { - regs->ARM_sp += 4; - force_sigsegv(0, current); - } -#endif - } - } + && regs->ARM_pc == restart_addr) + set_thread_flag(TIF_SYSCALL_RESTARTSYS); } /* If there's no signal to deliver, we just put the saved sigmask |