aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/signal.c')
-rw-r--r--arch/arm/kernel/signal.c86
1 files changed, 37 insertions, 49 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index b76fe06d92e7..1423a3419789 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -48,57 +48,22 @@ const unsigned long sigreturn_codes[7] = {
48 MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, 48 MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
49}; 49};
50 50
51static int do_signal(sigset_t *oldset, struct pt_regs * regs, int syscall);
52
53/* 51/*
54 * atomically swap in the new signal mask, and wait for a signal. 52 * atomically swap in the new signal mask, and wait for a signal.
55 */ 53 */
56asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs) 54asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
57{ 55{
58 sigset_t saveset;
59
60 mask &= _BLOCKABLE; 56 mask &= _BLOCKABLE;
61 spin_lock_irq(&current->sighand->siglock); 57 spin_lock_irq(&current->sighand->siglock);
62 saveset = current->blocked; 58 current->saved_sigmask = current->blocked;
63 siginitset(&current->blocked, mask); 59 siginitset(&current->blocked, mask);
64 recalc_sigpending(); 60 recalc_sigpending();
65 spin_unlock_irq(&current->sighand->siglock); 61 spin_unlock_irq(&current->sighand->siglock);
66 regs->ARM_r0 = -EINTR;
67
68 while (1) {
69 current->state = TASK_INTERRUPTIBLE;
70 schedule();
71 if (do_signal(&saveset, regs, 0))
72 return regs->ARM_r0;
73 }
74}
75
76asmlinkage int
77sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
78{
79 sigset_t saveset, newset;
80
81 /* XXX: Don't preclude handling different sized sigset_t's. */
82 if (sigsetsize != sizeof(sigset_t))
83 return -EINVAL;
84
85 if (copy_from_user(&newset, unewset, sizeof(newset)))
86 return -EFAULT;
87 sigdelsetmask(&newset, ~_BLOCKABLE);
88
89 spin_lock_irq(&current->sighand->siglock);
90 saveset = current->blocked;
91 current->blocked = newset;
92 recalc_sigpending();
93 spin_unlock_irq(&current->sighand->siglock);
94 regs->ARM_r0 = -EINTR;
95 62
96 while (1) { 63 current->state = TASK_INTERRUPTIBLE;
97 current->state = TASK_INTERRUPTIBLE; 64 schedule();
98 schedule(); 65 set_restore_sigmask();
99 if (do_signal(&saveset, regs, 0)) 66 return -ERESTARTNOHAND;
100 return regs->ARM_r0;
101 }
102} 67}
103 68
104asmlinkage int 69asmlinkage int
@@ -546,7 +511,7 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
546/* 511/*
547 * OK, we're invoking a handler 512 * OK, we're invoking a handler
548 */ 513 */
549static void 514static int
550handle_signal(unsigned long sig, struct k_sigaction *ka, 515handle_signal(unsigned long sig, struct k_sigaction *ka,
551 siginfo_t *info, sigset_t *oldset, 516 siginfo_t *info, sigset_t *oldset,
552 struct pt_regs * regs, int syscall) 517 struct pt_regs * regs, int syscall)
@@ -597,7 +562,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
597 562
598 if (ret != 0) { 563 if (ret != 0) {
599 force_sigsegv(sig, tsk); 564 force_sigsegv(sig, tsk);
600 return; 565 return ret;
601 } 566 }
602 567
603 /* 568 /*
@@ -611,6 +576,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
611 recalc_sigpending(); 576 recalc_sigpending();
612 spin_unlock_irq(&tsk->sighand->siglock); 577 spin_unlock_irq(&tsk->sighand->siglock);
613 578
579 return 0;
614} 580}
615 581
616/* 582/*
@@ -622,7 +588,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
622 * the kernel can handle, and then we build all the user-level signal handling 588 * the kernel can handle, and then we build all the user-level signal handling
623 * stack-frames in one go after that. 589 * stack-frames in one go after that.
624 */ 590 */
625static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) 591static void do_signal(struct pt_regs *regs, int syscall)
626{ 592{
627 struct k_sigaction ka; 593 struct k_sigaction ka;
628 siginfo_t info; 594 siginfo_t info;
@@ -635,7 +601,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
635 * if so. 601 * if so.
636 */ 602 */
637 if (!user_mode(regs)) 603 if (!user_mode(regs))
638 return 0; 604 return;
639 605
640 if (try_to_freeze()) 606 if (try_to_freeze())
641 goto no_signal; 607 goto no_signal;
@@ -644,9 +610,24 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
644 610
645 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 611 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
646 if (signr > 0) { 612 if (signr > 0) {
647 handle_signal(signr, &ka, &info, oldset, regs, syscall); 613 sigset_t *oldset;
614
615 if (test_thread_flag(TIF_RESTORE_SIGMASK))
616 oldset = &current->saved_sigmask;
617 else
618 oldset = &current->blocked;
619 if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
620 /*
621 * A signal was successfully delivered; the saved
622 * sigmask will have been stored in the signal frame,
623 * and will be restored by sigreturn, so we can simply
624 * clear the TIF_RESTORE_SIGMASK flag.
625 */
626 if (test_thread_flag(TIF_RESTORE_SIGMASK))
627 clear_thread_flag(TIF_RESTORE_SIGMASK);
628 }
648 single_step_set(current); 629 single_step_set(current);
649 return 1; 630 return;
650 } 631 }
651 632
652 no_signal: 633 no_signal:
@@ -698,16 +679,23 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
698 regs->ARM_r0 == -ERESTARTNOINTR) { 679 regs->ARM_r0 == -ERESTARTNOINTR) {
699 setup_syscall_restart(regs); 680 setup_syscall_restart(regs);
700 } 681 }
682
683 /* If there's no signal to deliver, we just put the saved sigmask
684 * back.
685 */
686 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
687 clear_thread_flag(TIF_RESTORE_SIGMASK);
688 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
689 }
701 } 690 }
702 single_step_set(current); 691 single_step_set(current);
703 return 0;
704} 692}
705 693
706asmlinkage void 694asmlinkage void
707do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall) 695do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall)
708{ 696{
709 if (thread_flags & _TIF_SIGPENDING) 697 if (thread_flags & _TIF_SIGPENDING)
710 do_signal(&current->blocked, regs, syscall); 698 do_signal(regs, syscall);
711 699
712 if (thread_flags & _TIF_NOTIFY_RESUME) { 700 if (thread_flags & _TIF_NOTIFY_RESUME) {
713 clear_thread_flag(TIF_NOTIFY_RESUME); 701 clear_thread_flag(TIF_NOTIFY_RESUME);