I don't think this will help, but it's worth a test, prior to totally re-writing entry.S. There's a chance of confusion of the value of regs->r0 if there is in fact no error. r~
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 6cec288..5b855c8 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -452,30 +452,6 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) signal_setup_done(ret, ksig, 0); } -static inline void -syscall_restart(unsigned long r0, unsigned long r19, - struct pt_regs *regs, struct k_sigaction *ka) -{ - switch (regs->r0) { - case ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - case ERESTARTNOHAND: - regs->r0 = EINTR; - break; - } - /* fallthrough */ - case ERESTARTNOINTR: - regs->r0 = r0; /* reset v0 and a3 and replay syscall */ - regs->r19 = r19; - regs->pc -= 4; - break; - case ERESTART_RESTARTBLOCK: - regs->r0 = EINTR; - break; - } -} - - /* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by @@ -499,13 +475,35 @@ do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19) if (get_signal(&ksig)) { /* ... so re-check the single stepping. */ single_stepping |= ptrace_cancel_bpt(current); + + /* Are we coming from a syscall error? */ + if (r0 && regs->r19) { + switch (regs->r0) { + case ERESTARTSYS: + if (!(ksig.ka.sa.sa_flags & SA_RESTART)) { + case ERESTARTNOHAND: + case ERESTART_RESTARTBLOCK: + regs->r0 = EINTR; + regs->r19 = 1; + break; + } + /* fallthrough */ + case ERESTARTNOINTR: + /* Reset v0 and a3 for syscall replay. */ + regs->r0 = r0; + regs->r19 = r19; + regs->pc -= 4; + break; + } + } + /* Whee! Actually deliver the signal. */ - if (r0) - syscall_restart(r0, r19, regs, &ksig.ka); handle_signal(&ksig, regs); } else { single_stepping |= ptrace_cancel_bpt(current); - if (r0) { + + /* Are we coming from a syscall error? */ + if (r0 && regs->r19) { switch (regs->r0) { case ERESTARTNOHAND: case ERESTARTSYS: @@ -522,6 +520,7 @@ do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19) break; } } + restore_saved_sigmask(); } if (single_stepping)