aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2006-01-18 20:43:57 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-18 22:20:29 -0500
commit150256d8aadb3a337c31efa9e175cbd25bf06b06 (patch)
tree8cd7e2a0bc6af23984682c5ea3ca687809580c5a
parenta60fc5190a31d98508ea6a76f74217f4104e74b7 (diff)
[PATCH] Generic sys_rt_sigsuspend()
The TIF_RESTORE_SIGMASK flag allows us to have a generic implementation of sys_rt_sigsuspend() instead of duplicating it for each architecture. This provides such an implementation and makes arch/powerpc use it. It also tidies up the ppc32 sys_sigsuspend() to use TIF_RESTORE_SIGMASK. Signed-off-by: David Woodhouse <dwmw2@infradead.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/powerpc/kernel/signal_32.c56
-rw-r--r--arch/powerpc/kernel/signal_64.c36
-rw-r--r--include/asm-powerpc/unistd.h2
-rw-r--r--include/linux/sched.h1
-rw-r--r--kernel/compat.c28
-rw-r--r--kernel/signal.c26
6 files changed, 62 insertions, 87 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 177bba78fb0b..7f0d5ce2567d 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -252,8 +252,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs);
252/* 252/*
253 * Atomically swap in the new signal mask, and wait for a signal. 253 * Atomically swap in the new signal mask, and wait for a signal.
254 */ 254 */
255long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7, 255long sys_sigsuspend(old_sigset_t mask)
256 struct pt_regs *regs)
257{ 256{
258 sigset_t saveset; 257 sigset_t saveset;
259 258
@@ -264,55 +263,10 @@ long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
264 recalc_sigpending(); 263 recalc_sigpending();
265 spin_unlock_irq(&current->sighand->siglock); 264 spin_unlock_irq(&current->sighand->siglock);
266 265
267 regs->result = -EINTR; 266 current->state = TASK_INTERRUPTIBLE;
268 regs->gpr[3] = EINTR; 267 schedule();
269 regs->ccr |= 0x10000000; 268 set_thread_flag(TIF_RESTORE_SIGMASK);
270 while (1) { 269 return -ERESTARTNOHAND;
271 current->state = TASK_INTERRUPTIBLE;
272 schedule();
273 if (do_signal(&saveset, regs)) {
274 set_thread_flag(TIF_RESTOREALL);
275 return 0;
276 }
277 }
278}
279
280long sys_rt_sigsuspend(
281#ifdef CONFIG_PPC64
282 compat_sigset_t __user *unewset,
283#else
284 sigset_t __user *unewset,
285#endif
286 size_t sigsetsize, int p3, int p4,
287 int p6, int p7, struct pt_regs *regs)
288{
289 sigset_t saveset, newset;
290
291 /* XXX: Don't preclude handling different sized sigset_t's. */
292 if (sigsetsize != sizeof(sigset_t))
293 return -EINVAL;
294
295 if (get_sigset_t(&newset, unewset))
296 return -EFAULT;
297 sigdelsetmask(&newset, ~_BLOCKABLE);
298
299 spin_lock_irq(&current->sighand->siglock);
300 saveset = current->blocked;
301 current->blocked = newset;
302 recalc_sigpending();
303 spin_unlock_irq(&current->sighand->siglock);
304
305 regs->result = -EINTR;
306 regs->gpr[3] = EINTR;
307 regs->ccr |= 0x10000000;
308 while (1) {
309 current->state = TASK_INTERRUPTIBLE;
310 schedule();
311 if (do_signal(&saveset, regs)) {
312 set_thread_flag(TIF_RESTOREALL);
313 return 0;
314 }
315 }
316} 270}
317 271
318#ifdef CONFIG_PPC32 272#ifdef CONFIG_PPC32
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index 7b9d999e2115..a4a6812e815e 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -67,42 +67,6 @@ struct rt_sigframe {
67 char abigap[288]; 67 char abigap[288];
68} __attribute__ ((aligned (16))); 68} __attribute__ ((aligned (16)));
69 69
70
71/*
72 * Atomically swap in the new signal mask, and wait for a signal.
73 */
74long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4,
75 int p6, int p7, struct pt_regs *regs)
76{
77 sigset_t saveset, newset;
78
79 /* XXX: Don't preclude handling different sized sigset_t's. */
80 if (sigsetsize != sizeof(sigset_t))
81 return -EINVAL;
82
83 if (copy_from_user(&newset, unewset, sizeof(newset)))
84 return -EFAULT;
85 sigdelsetmask(&newset, ~_BLOCKABLE);
86
87 spin_lock_irq(&current->sighand->siglock);
88 saveset = current->blocked;
89 current->blocked = newset;
90 recalc_sigpending();
91 spin_unlock_irq(&current->sighand->siglock);
92
93 regs->result = -EINTR;
94 regs->gpr[3] = EINTR;
95 regs->ccr |= 0x10000000;
96 while (1) {
97 current->state = TASK_INTERRUPTIBLE;
98 schedule();
99 if (do_signal(&saveset, regs)) {
100 set_thread_flag(TIF_RESTOREALL);
101 return 0;
102 }
103 }
104}
105
106long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5, 70long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
107 unsigned long r6, unsigned long r7, unsigned long r8, 71 unsigned long r6, unsigned long r7, unsigned long r8,
108 struct pt_regs *regs) 72 struct pt_regs *regs)
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 19eaac3fbbf9..76daec496062 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -444,11 +444,13 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
444#define __ARCH_WANT_SYS_SIGPENDING 444#define __ARCH_WANT_SYS_SIGPENDING
445#define __ARCH_WANT_SYS_SIGPROCMASK 445#define __ARCH_WANT_SYS_SIGPROCMASK
446#define __ARCH_WANT_SYS_RT_SIGACTION 446#define __ARCH_WANT_SYS_RT_SIGACTION
447#define __ARCH_WANT_SYS_RT_SIGSUSPEND
447#ifdef CONFIG_PPC32 448#ifdef CONFIG_PPC32
448#define __ARCH_WANT_OLD_STAT 449#define __ARCH_WANT_OLD_STAT
449#endif 450#endif
450#ifdef CONFIG_PPC64 451#ifdef CONFIG_PPC64
451#define __ARCH_WANT_COMPAT_SYS_TIME 452#define __ARCH_WANT_COMPAT_SYS_TIME
453#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
452#endif 454#endif
453 455
454/* 456/*
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2df1a1a2fee5..0cfcd1c7865e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -809,6 +809,7 @@ struct task_struct {
809 struct sighand_struct *sighand; 809 struct sighand_struct *sighand;
810 810
811 sigset_t blocked, real_blocked; 811 sigset_t blocked, real_blocked;
812 sigset_t saved_sigmask; /* To be restored with TIF_RESTORE_SIGMASK */
812 struct sigpending pending; 813 struct sigpending pending;
813 814
814 unsigned long sas_ss_sp; 815 unsigned long sas_ss_sp;
diff --git a/kernel/compat.c b/kernel/compat.c
index 256e5d9f0647..1867290c37e3 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -871,3 +871,31 @@ asmlinkage long compat_sys_stime(compat_time_t __user *tptr)
871} 871}
872 872
873#endif /* __ARCH_WANT_COMPAT_SYS_TIME */ 873#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
874
875#ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
876asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize)
877{
878 sigset_t newset;
879 compat_sigset_t newset32;
880
881 /* XXX: Don't preclude handling different sized sigset_t's. */
882 if (sigsetsize != sizeof(sigset_t))
883 return -EINVAL;
884
885 if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
886 return -EFAULT;
887 sigset_from_compat(&newset, &newset32);
888 sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
889
890 spin_lock_irq(&current->sighand->siglock);
891 current->saved_sigmask = current->blocked;
892 current->blocked = newset;
893 recalc_sigpending();
894 spin_unlock_irq(&current->sighand->siglock);
895
896 current->state = TASK_INTERRUPTIBLE;
897 schedule();
898 set_thread_flag(TIF_RESTORE_SIGMASK);
899 return -ERESTARTNOHAND;
900}
901#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
diff --git a/kernel/signal.c b/kernel/signal.c
index 5dafbd36d62e..d3efafd8109a 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2721,6 +2721,32 @@ sys_pause(void)
2721 2721
2722#endif 2722#endif
2723 2723
2724#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
2725asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
2726{
2727 sigset_t newset;
2728
2729 /* XXX: Don't preclude handling different sized sigset_t's. */
2730 if (sigsetsize != sizeof(sigset_t))
2731 return -EINVAL;
2732
2733 if (copy_from_user(&newset, unewset, sizeof(newset)))
2734 return -EFAULT;
2735 sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
2736
2737 spin_lock_irq(&current->sighand->siglock);
2738 current->saved_sigmask = current->blocked;
2739 current->blocked = newset;
2740 recalc_sigpending();
2741 spin_unlock_irq(&current->sighand->siglock);
2742
2743 current->state = TASK_INTERRUPTIBLE;
2744 schedule();
2745 set_thread_flag(TIF_RESTORE_SIGMASK);
2746 return -ERESTARTNOHAND;
2747}
2748#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
2749
2724void __init signals_init(void) 2750void __init signals_init(void)
2725{ 2751{
2726 sigqueue_cachep = 2752 sigqueue_cachep =