diff options
-rw-r--r-- | arch/sh/kernel/signal_64.c | 93 |
1 files changed, 48 insertions, 45 deletions
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index ce3e851dffcb..08828ddd97ff 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * arch/sh/kernel/signal_64.c | 2 | * arch/sh/kernel/signal_64.c |
3 | * | 3 | * |
4 | * Copyright (C) 2000, 2001 Paolo Alberelli | 4 | * Copyright (C) 2000, 2001 Paolo Alberelli |
5 | * Copyright (C) 2003 Paul Mundt | 5 | * Copyright (C) 2003 - 2008 Paul Mundt |
6 | * Copyright (C) 2004 Richard Curnow | 6 | * Copyright (C) 2004 Richard Curnow |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
@@ -43,7 +43,7 @@ | |||
43 | 43 | ||
44 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 44 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
45 | 45 | ||
46 | static void | 46 | static int |
47 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 47 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
48 | sigset_t *oldset, struct pt_regs * regs); | 48 | sigset_t *oldset, struct pt_regs * regs); |
49 | 49 | ||
@@ -80,21 +80,20 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
80 | oldset = ¤t->blocked; | 80 | oldset = ¤t->blocked; |
81 | 81 | ||
82 | signr = get_signal_to_deliver(&info, &ka, regs, 0); | 82 | signr = get_signal_to_deliver(&info, &ka, regs, 0); |
83 | |||
84 | if (signr > 0) { | 83 | if (signr > 0) { |
85 | /* Whee! Actually deliver the signal. */ | 84 | /* Whee! Actually deliver the signal. */ |
86 | handle_signal(signr, &info, &ka, oldset, regs); | 85 | if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { |
87 | 86 | /* | |
88 | /* | 87 | * If a signal was successfully delivered, the |
89 | * If a signal was successfully delivered, the saved sigmask | 88 | * saved sigmask is in its frame, and we can |
90 | * is in its frame, and we can clear the TIF_RESTORE_SIGMASK | 89 | * clear the TIF_RESTORE_SIGMASK flag. |
91 | * flag. | 90 | */ |
92 | */ | 91 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
93 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | 92 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
94 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 93 | |
95 | 94 | tracehook_signal_handler(signr, &info, &ka, regs, 0); | |
96 | tracehook_signal_handler(signr, &info, &ka, regs, 0); | 95 | return 1; |
97 | return 1; | 96 | } |
98 | } | 97 | } |
99 | 98 | ||
100 | no_signal: | 99 | no_signal: |
@@ -504,8 +503,8 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) | |||
504 | void sa_default_restorer(void); /* See comments below */ | 503 | void sa_default_restorer(void); /* See comments below */ |
505 | void sa_default_rt_restorer(void); /* See comments below */ | 504 | void sa_default_rt_restorer(void); /* See comments below */ |
506 | 505 | ||
507 | static void setup_frame(int sig, struct k_sigaction *ka, | 506 | static int setup_frame(int sig, struct k_sigaction *ka, |
508 | sigset_t *set, struct pt_regs *regs) | 507 | sigset_t *set, struct pt_regs *regs) |
509 | { | 508 | { |
510 | struct sigframe __user *frame; | 509 | struct sigframe __user *frame; |
511 | int err = 0; | 510 | int err = 0; |
@@ -596,23 +595,21 @@ static void setup_frame(int sig, struct k_sigaction *ka, | |||
596 | 595 | ||
597 | set_fs(USER_DS); | 596 | set_fs(USER_DS); |
598 | 597 | ||
599 | #if DEBUG_SIG | ||
600 | /* Broken %016Lx */ | 598 | /* Broken %016Lx */ |
601 | printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", | 599 | pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", |
602 | signal, | 600 | signal, current->comm, current->pid, frame, |
603 | current->comm, current->pid, frame, | 601 | regs->pc >> 32, regs->pc & 0xffffffff, |
604 | regs->pc >> 32, regs->pc & 0xffffffff, | 602 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); |
605 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); | ||
606 | #endif | ||
607 | 603 | ||
608 | return; | 604 | return 0; |
609 | 605 | ||
610 | give_sigsegv: | 606 | give_sigsegv: |
611 | force_sigsegv(sig, current); | 607 | force_sigsegv(sig, current); |
608 | return -EFAULT; | ||
612 | } | 609 | } |
613 | 610 | ||
614 | static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 611 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
615 | sigset_t *set, struct pt_regs *regs) | 612 | sigset_t *set, struct pt_regs *regs) |
616 | { | 613 | { |
617 | struct rt_sigframe __user *frame; | 614 | struct rt_sigframe __user *frame; |
618 | int err = 0; | 615 | int err = 0; |
@@ -702,29 +699,28 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
702 | 699 | ||
703 | set_fs(USER_DS); | 700 | set_fs(USER_DS); |
704 | 701 | ||
705 | #if DEBUG_SIG | 702 | pr_debug("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", |
706 | /* Broken %016Lx */ | 703 | signal, current->comm, current->pid, frame, |
707 | printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", | 704 | regs->pc >> 32, regs->pc & 0xffffffff, |
708 | signal, | 705 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); |
709 | current->comm, current->pid, frame, | ||
710 | regs->pc >> 32, regs->pc & 0xffffffff, | ||
711 | DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); | ||
712 | #endif | ||
713 | 706 | ||
714 | return; | 707 | return 0; |
715 | 708 | ||
716 | give_sigsegv: | 709 | give_sigsegv: |
717 | force_sigsegv(sig, current); | 710 | force_sigsegv(sig, current); |
711 | return -EFAULT; | ||
718 | } | 712 | } |
719 | 713 | ||
720 | /* | 714 | /* |
721 | * OK, we're invoking a handler | 715 | * OK, we're invoking a handler |
722 | */ | 716 | */ |
723 | 717 | ||
724 | static void | 718 | static int |
725 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 719 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
726 | sigset_t *oldset, struct pt_regs * regs) | 720 | sigset_t *oldset, struct pt_regs * regs) |
727 | { | 721 | { |
722 | int ret; | ||
723 | |||
728 | /* Are we from a system call? */ | 724 | /* Are we from a system call? */ |
729 | if (regs->syscall_nr >= 0) { | 725 | if (regs->syscall_nr >= 0) { |
730 | /* If so, check system call restarting.. */ | 726 | /* If so, check system call restarting.. */ |
@@ -748,16 +744,23 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
748 | 744 | ||
749 | /* Set up the stack frame */ | 745 | /* Set up the stack frame */ |
750 | if (ka->sa.sa_flags & SA_SIGINFO) | 746 | if (ka->sa.sa_flags & SA_SIGINFO) |
751 | setup_rt_frame(sig, ka, info, oldset, regs); | 747 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
752 | else | 748 | else |
753 | setup_frame(sig, ka, oldset, regs); | 749 | ret = setup_frame(sig, ka, oldset, regs); |
750 | |||
751 | if (ka->sa.sa_flags & SA_ONESHOT) | ||
752 | ka->sa.sa_handler = SIG_DFL; | ||
753 | |||
754 | if (ret == 0) { | ||
755 | spin_lock_irq(¤t->sighand->siglock); | ||
756 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
757 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
758 | sigaddset(¤t->blocked,sig); | ||
759 | recalc_sigpending(); | ||
760 | spin_unlock_irq(¤t->sighand->siglock); | ||
761 | } | ||
754 | 762 | ||
755 | spin_lock_irq(¤t->sighand->siglock); | 763 | return ret; |
756 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
757 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
758 | sigaddset(¤t->blocked,sig); | ||
759 | recalc_sigpending(); | ||
760 | spin_unlock_irq(¤t->sighand->siglock); | ||
761 | } | 764 | } |
762 | 765 | ||
763 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | 766 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) |