aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/signal.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 20:48:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-14 20:48:14 -0400
commit2ca7d674d7ab2220707b2ada0b690c0e7c95e7ac (patch)
tree9c0927ed1d540e5fd704c1f82689870786514655 /arch/arm/kernel/signal.c
parent2195d2818c37bdf263865f1e9effccdd9fc5f9d4 (diff)
parent87d721ad7a37b7650dd710c88dd5c6a5bf9fe996 (diff)
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (257 commits) [ARM] Update mach-types ARM: 5636/1: Move vendor enum to AMBA include ARM: Fix pfn_valid() for sparse memory [ARM] orion5x: Add LaCie NAS 2Big Network support [ARM] pxa/sharpsl_pm: zaurus c3000 aka spitz: fix resume ARM: 5686/1: at91: Correct AC97 reset line in at91sam9263ek board ARM: 5640/1: This patch modifies the support of AC97 on the at91sam9263 ek board ARM: 5689/1: Update default config of HP Jornada 700-series machines ARM: 5691/1: fix cache aliasing issues between kmap() and kmap_atomic() with highmem ARM: 5688/1: ks8695_serial: disable_irq() lockup ARM: 5687/1: fix an oops with highmem ARM: 5684/1: Add nuc960 platform to w90x900 ARM: 5683/1: Add nuc950 platform to w90x900 ARM: 5682/1: Add cpu.c and dev.c and modify some files of w90p910 platform ARM: 5626/1: add suspend/resume functions to amba-pl011 serial driver ARM: 5625/1: fix hard coded 4K resource size in amba bus detection MMC: MMCI: convert realview MMC to use gpiolib ARM: 5685/1: Make MMCI driver compile without gpiolib ARM: implement highpte ARM: Show FIQ in /proc/interrupts on CONFIG_FIQ ... Fix up trivial conflict in arch/arm/kernel/signal.c. It was due to the TIF_NOTIFY_RESUME addition in commit d0420c83f ("KEYS: Extend TIF_NOTIFY_RESUME to (almost) all architectures") and follow-ups.
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);