aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2008-09-12 09:08:20 -0400
committerPaul Mundt <lethal@linux-sh.org>2008-09-12 09:08:20 -0400
commitf8b890ab4ca60c05b5621b267712709d329f7612 (patch)
treeef79531765dd63e12b9506299b45abb24938de21 /arch/sh/kernel
parentcb700aa4f13d38726defab3060d3ebeaf67dc189 (diff)
sh: Flag T-bit for syscall restart.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/signal_32.c53
1 files changed, 31 insertions, 22 deletions
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index 345de2f1d53c..be194d0bd7d2 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -490,37 +490,43 @@ give_sigsegv:
490 return -EFAULT; 490 return -EFAULT;
491} 491}
492 492
493static inline void
494handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
495 struct sigaction *sa)
496{
497 /* If we're not from a syscall, bail out */
498 if (regs->tra < 0)
499 return;
500
501 /* check for system call restart.. */
502 switch (regs->regs[0]) {
503 case -ERESTART_RESTARTBLOCK:
504 case -ERESTARTNOHAND:
505 no_system_call_restart:
506 regs->regs[0] = -EINTR;
507 regs->sr |= 1;
508 break;
509
510 case -ERESTARTSYS:
511 if (!(sa->sa_flags & SA_RESTART))
512 goto no_system_call_restart;
513 /* fallthrough */
514 case -ERESTARTNOINTR:
515 regs->regs[0] = save_r0;
516 regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
517 break;
518 }
519}
520
493/* 521/*
494 * OK, we're invoking a handler 522 * OK, we're invoking a handler
495 */ 523 */
496
497static int 524static int
498handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, 525handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
499 sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0) 526 sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0)
500{ 527{
501 int ret; 528 int ret;
502 529
503 /* Are we from a system call? */
504 if (regs->tra >= 0) {
505 /* If so, check system call restarting.. */
506 switch (regs->regs[0]) {
507 case -ERESTART_RESTARTBLOCK:
508 case -ERESTARTNOHAND:
509 no_system_call_restart:
510 regs->regs[0] = -EINTR;
511 break;
512
513 case -ERESTARTSYS:
514 if (!(ka->sa.sa_flags & SA_RESTART))
515 goto no_system_call_restart;
516 /* fallthrough */
517 case -ERESTARTNOINTR:
518 regs->regs[0] = save_r0;
519 regs->pc -= instruction_size(
520 ctrl_inw(regs->pc - 4));
521 break;
522 }
523 }
524 530
525 /* Set up the stack frame */ 531 /* Set up the stack frame */
526 if (ka->sa.sa_flags & SA_SIGINFO) 532 if (ka->sa.sa_flags & SA_SIGINFO)
@@ -578,6 +584,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
578 584
579 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 585 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
580 if (signr > 0) { 586 if (signr > 0) {
587 if (regs->sr & 1)
588 handle_syscall_restart(save_r0, regs, &ka.sa);
589
581 /* Whee! Actually deliver the signal. */ 590 /* Whee! Actually deliver the signal. */
582 if (handle_signal(signr, &ka, &info, oldset, 591 if (handle_signal(signr, &ka, &info, oldset,
583 regs, save_r0) == 0) { 592 regs, save_r0) == 0) {