|
@@ -605,10 +605,12 @@ 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;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -624,14 +626,12 @@ 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 ||
|
|
|
- retval == -ERESTART_RESTARTBLOCK
|
|
|
+ if (retval == -ERESTARTNOHAND
|
|
|
|| (retval == -ERESTARTSYS
|
|
|
&& !(ka.sa.sa_flags & SA_RESTART))) {
|
|
|
regs->ARM_r0 = -EINTR;
|
|
|
regs->ARM_pc = continue_addr;
|
|
|
}
|
|
|
- clear_thread_flag(TIF_SYSCALL_RESTARTSYS);
|
|
|
}
|
|
|
|
|
|
handle_signal(signr, &ka, &info, regs);
|
|
@@ -645,8 +645,29 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
|
|
* ignore the restart.
|
|
|
*/
|
|
|
if (retval == -ERESTART_RESTARTBLOCK
|
|
|
- && regs->ARM_pc == restart_addr)
|
|
|
- set_thread_flag(TIF_SYSCALL_RESTARTSYS);
|
|
|
+ && 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
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
restore_saved_sigmask();
|