diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 20:48:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 20:48:14 -0400 |
commit | 2ca7d674d7ab2220707b2ada0b690c0e7c95e7ac (patch) | |
tree | 9c0927ed1d540e5fd704c1f82689870786514655 /arch/arm/kernel/signal.c | |
parent | 2195d2818c37bdf263865f1e9effccdd9fc5f9d4 (diff) | |
parent | 87d721ad7a37b7650dd710c88dd5c6a5bf9fe996 (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.c | 86 |
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 | ||
51 | static 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 | */ |
56 | asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs) | 54 | asmlinkage 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(¤t->sighand->siglock); | 57 | spin_lock_irq(¤t->sighand->siglock); |
62 | saveset = current->blocked; | 58 | current->saved_sigmask = current->blocked; |
63 | siginitset(¤t->blocked, mask); | 59 | siginitset(¤t->blocked, mask); |
64 | recalc_sigpending(); | 60 | recalc_sigpending(); |
65 | spin_unlock_irq(¤t->sighand->siglock); | 61 | spin_unlock_irq(¤t->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 | |||
76 | asmlinkage int | ||
77 | sys_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(¤t->sighand->siglock); | ||
90 | saveset = current->blocked; | ||
91 | current->blocked = newset; | ||
92 | recalc_sigpending(); | ||
93 | spin_unlock_irq(¤t->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 | ||
104 | asmlinkage int | 69 | asmlinkage 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 | */ |
549 | static void | 514 | static int |
550 | handle_signal(unsigned long sig, struct k_sigaction *ka, | 515 | handle_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 | */ |
625 | static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) | 591 | static 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 = ¤t->saved_sigmask; | ||
617 | else | ||
618 | oldset = ¤t->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, ¤t->saved_sigmask, NULL); | ||
689 | } | ||
701 | } | 690 | } |
702 | single_step_set(current); | 691 | single_step_set(current); |
703 | return 0; | ||
704 | } | 692 | } |
705 | 693 | ||
706 | asmlinkage void | 694 | asmlinkage void |
707 | do_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall) | 695 | do_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(¤t->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); |