aboutsummaryrefslogtreecommitdiffstats
path: root/arch/m68knommu/kernel/signal.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2010-10-11 17:09:20 -0400
committerGeert Uytterhoeven <geert@linux-m68k.org>2011-01-07 08:06:59 -0500
commit710e91e455caf5cfec02892d667b41f312ec166c (patch)
tree9e6f3d5c3dcb387809cab3cbc04060768b8a75db /arch/m68knommu/kernel/signal.c
parentbf814b45d560b22e8657ca44d0ae6941ab9d8d36 (diff)
m68knommu: Switch to saner sigsuspend
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Acked-by: Greg Ungerer <gerg@uclinux.org> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Diffstat (limited to 'arch/m68knommu/kernel/signal.c')
-rw-r--r--arch/m68knommu/kernel/signal.c63
1 files changed, 19 insertions, 44 deletions
diff --git a/arch/m68knommu/kernel/signal.c b/arch/m68knommu/kernel/signal.c
index 1934de7aaf6c..c973230dad82 100644
--- a/arch/m68knommu/kernel/signal.c
+++ b/arch/m68knommu/kernel/signal.c
@@ -53,60 +53,25 @@
53 53
54void ret_from_user_signal(void); 54void ret_from_user_signal(void);
55void ret_from_user_rt_signal(void); 55void ret_from_user_rt_signal(void);
56asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs);
57 56
58/* 57/*
59 * Atomically swap in the new signal mask, and wait for a signal. 58 * Atomically swap in the new signal mask, and wait for a signal.
60 */ 59 */
61asmlinkage int do_sigsuspend(struct pt_regs *regs) 60asmlinkage int
61sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
62{ 62{
63 old_sigset_t mask = regs->d3;
64 sigset_t saveset;
65
66 mask &= _BLOCKABLE; 63 mask &= _BLOCKABLE;
67 spin_lock_irq(&current->sighand->siglock); 64 spin_lock_irq(&current->sighand->siglock);
68 saveset = current->blocked; 65 current->saved_sigmask = current->blocked;
69 siginitset(&current->blocked, mask); 66 siginitset(&current->blocked, mask);
70 recalc_sigpending(); 67 recalc_sigpending();
71 spin_unlock_irq(&current->sighand->siglock); 68 spin_unlock_irq(&current->sighand->siglock);
72 69
73 regs->d0 = -EINTR; 70 current->state = TASK_INTERRUPTIBLE;
74 while (1) { 71 schedule();
75 current->state = TASK_INTERRUPTIBLE; 72 set_restore_sigmask();
76 schedule();
77 if (do_signal(&saveset, regs))
78 return -EINTR;
79 }
80}
81
82asmlinkage int
83do_rt_sigsuspend(struct pt_regs *regs)
84{
85 sigset_t *unewset = (sigset_t *)regs->d1;
86 size_t sigsetsize = (size_t)regs->d2;
87 sigset_t saveset, newset;
88
89 /* XXX: Don't preclude handling different sized sigset_t's. */
90 if (sigsetsize != sizeof(sigset_t))
91 return -EINVAL;
92
93 if (copy_from_user(&newset, unewset, sizeof(newset)))
94 return -EFAULT;
95 sigdelsetmask(&newset, ~_BLOCKABLE);
96 73
97 spin_lock_irq(&current->sighand->siglock); 74 return -ERESTARTNOHAND;
98 saveset = current->blocked;
99 current->blocked = newset;
100 recalc_sigpending();
101 spin_unlock_irq(&current->sighand->siglock);
102
103 regs->d0 = -EINTR;
104 while (1) {
105 current->state = TASK_INTERRUPTIBLE;
106 schedule();
107 if (do_signal(&saveset, regs))
108 return -EINTR;
109 }
110} 75}
111 76
112asmlinkage int 77asmlinkage int
@@ -752,11 +717,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
752 * want to handle. Thus you cannot kill init even with a SIGKILL even by 717 * want to handle. Thus you cannot kill init even with a SIGKILL even by
753 * mistake. 718 * mistake.
754 */ 719 */
755asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) 720asmlinkage int do_signal(struct pt_regs *regs)
756{ 721{
757 struct k_sigaction ka; 722 struct k_sigaction ka;
758 siginfo_t info; 723 siginfo_t info;
759 int signr; 724 int signr;
725 sigset_t *oldset;
760 726
761 /* 727 /*
762 * We want the common case to go fast, which 728 * We want the common case to go fast, which
@@ -767,13 +733,16 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
767 if (!user_mode(regs)) 733 if (!user_mode(regs))
768 return 1; 734 return 1;
769 735
770 if (!oldset) 736 if (test_thread_flag(TIF_RESTORE_SIGMASK))
737 oldset = &current->saved_sigmask;
738 else
771 oldset = &current->blocked; 739 oldset = &current->blocked;
772 740
773 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 741 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
774 if (signr > 0) { 742 if (signr > 0) {
775 /* Whee! Actually deliver the signal. */ 743 /* Whee! Actually deliver the signal. */
776 handle_signal(signr, &ka, &info, oldset, regs); 744 handle_signal(signr, &ka, &info, oldset, regs);
745 clear_thread_flag(TIF_RESTORE_SIGMASK);
777 return 1; 746 return 1;
778 } 747 }
779 748
@@ -782,5 +751,11 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
782 /* Restart the system call - no handlers present */ 751 /* Restart the system call - no handlers present */
783 handle_restart(regs, NULL, 0); 752 handle_restart(regs, NULL, 0);
784 } 753 }
754
755 /* If there's no signal to deliver, we just restore the saved mask. */
756 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
757 clear_thread_flag(TIF_RESTORE_SIGMASK);
758 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
759 }
785 return 0; 760 return 0;
786} 761}