[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>
This commit is contained in:
Родитель
a60fc5190a
Коммит
150256d8aa
|
@ -252,8 +252,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs);
|
||||||
/*
|
/*
|
||||||
* Atomically swap in the new signal mask, and wait for a signal.
|
* Atomically swap in the new signal mask, and wait for a signal.
|
||||||
*/
|
*/
|
||||||
long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
|
long sys_sigsuspend(old_sigset_t mask)
|
||||||
struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
sigset_t saveset;
|
sigset_t saveset;
|
||||||
|
|
||||||
|
@ -264,55 +263,10 @@ long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
|
||||||
recalc_sigpending();
|
recalc_sigpending();
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
|
|
||||||
regs->result = -EINTR;
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
regs->gpr[3] = EINTR;
|
schedule();
|
||||||
regs->ccr |= 0x10000000;
|
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
while (1) {
|
return -ERESTARTNOHAND;
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
if (do_signal(&saveset, regs)) {
|
|
||||||
set_thread_flag(TIF_RESTOREALL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long sys_rt_sigsuspend(
|
|
||||||
#ifdef CONFIG_PPC64
|
|
||||||
compat_sigset_t __user *unewset,
|
|
||||||
#else
|
|
||||||
sigset_t __user *unewset,
|
|
||||||
#endif
|
|
||||||
size_t sigsetsize, int p3, int p4,
|
|
||||||
int p6, int p7, struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
sigset_t saveset, newset;
|
|
||||||
|
|
||||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
|
||||||
if (sigsetsize != sizeof(sigset_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (get_sigset_t(&newset, unewset))
|
|
||||||
return -EFAULT;
|
|
||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
saveset = current->blocked;
|
|
||||||
current->blocked = newset;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
regs->result = -EINTR;
|
|
||||||
regs->gpr[3] = EINTR;
|
|
||||||
regs->ccr |= 0x10000000;
|
|
||||||
while (1) {
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
if (do_signal(&saveset, regs)) {
|
|
||||||
set_thread_flag(TIF_RESTOREALL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PPC32
|
#ifdef CONFIG_PPC32
|
||||||
|
|
|
@ -67,42 +67,6 @@ struct rt_sigframe {
|
||||||
char abigap[288];
|
char abigap[288];
|
||||||
} __attribute__ ((aligned (16)));
|
} __attribute__ ((aligned (16)));
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Atomically swap in the new signal mask, and wait for a signal.
|
|
||||||
*/
|
|
||||||
long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, int p3, int p4,
|
|
||||||
int p6, int p7, struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
sigset_t saveset, newset;
|
|
||||||
|
|
||||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
|
||||||
if (sigsetsize != sizeof(sigset_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
|
||||||
return -EFAULT;
|
|
||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
saveset = current->blocked;
|
|
||||||
current->blocked = newset;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
regs->result = -EINTR;
|
|
||||||
regs->gpr[3] = EINTR;
|
|
||||||
regs->ccr |= 0x10000000;
|
|
||||||
while (1) {
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
if (do_signal(&saveset, regs)) {
|
|
||||||
set_thread_flag(TIF_RESTOREALL);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
|
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
|
||||||
unsigned long r6, unsigned long r7, unsigned long r8,
|
unsigned long r6, unsigned long r7, unsigned long r8,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
|
|
|
@ -444,11 +444,13 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6
|
||||||
#define __ARCH_WANT_SYS_SIGPENDING
|
#define __ARCH_WANT_SYS_SIGPENDING
|
||||||
#define __ARCH_WANT_SYS_SIGPROCMASK
|
#define __ARCH_WANT_SYS_SIGPROCMASK
|
||||||
#define __ARCH_WANT_SYS_RT_SIGACTION
|
#define __ARCH_WANT_SYS_RT_SIGACTION
|
||||||
|
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||||
#ifdef CONFIG_PPC32
|
#ifdef CONFIG_PPC32
|
||||||
#define __ARCH_WANT_OLD_STAT
|
#define __ARCH_WANT_OLD_STAT
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PPC64
|
#ifdef CONFIG_PPC64
|
||||||
#define __ARCH_WANT_COMPAT_SYS_TIME
|
#define __ARCH_WANT_COMPAT_SYS_TIME
|
||||||
|
#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -809,6 +809,7 @@ struct task_struct {
|
||||||
struct sighand_struct *sighand;
|
struct sighand_struct *sighand;
|
||||||
|
|
||||||
sigset_t blocked, real_blocked;
|
sigset_t blocked, real_blocked;
|
||||||
|
sigset_t saved_sigmask; /* To be restored with TIF_RESTORE_SIGMASK */
|
||||||
struct sigpending pending;
|
struct sigpending pending;
|
||||||
|
|
||||||
unsigned long sas_ss_sp;
|
unsigned long sas_ss_sp;
|
||||||
|
|
|
@ -871,3 +871,31 @@ asmlinkage long compat_sys_stime(compat_time_t __user *tptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
|
#endif /* __ARCH_WANT_COMPAT_SYS_TIME */
|
||||||
|
|
||||||
|
#ifdef __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
|
||||||
|
asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize)
|
||||||
|
{
|
||||||
|
sigset_t newset;
|
||||||
|
compat_sigset_t newset32;
|
||||||
|
|
||||||
|
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||||
|
if (sigsetsize != sizeof(sigset_t))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
|
||||||
|
return -EFAULT;
|
||||||
|
sigset_from_compat(&newset, &newset32);
|
||||||
|
sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
|
||||||
|
|
||||||
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
|
current->saved_sigmask = current->blocked;
|
||||||
|
current->blocked = newset;
|
||||||
|
recalc_sigpending();
|
||||||
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
|
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
schedule();
|
||||||
|
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
|
return -ERESTARTNOHAND;
|
||||||
|
}
|
||||||
|
#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
|
||||||
|
|
|
@ -2721,6 +2721,32 @@ sys_pause(void)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||||
|
asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize)
|
||||||
|
{
|
||||||
|
sigset_t newset;
|
||||||
|
|
||||||
|
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||||
|
if (sigsetsize != sizeof(sigset_t))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
||||||
|
return -EFAULT;
|
||||||
|
sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
|
||||||
|
|
||||||
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
|
current->saved_sigmask = current->blocked;
|
||||||
|
current->blocked = newset;
|
||||||
|
recalc_sigpending();
|
||||||
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
|
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
schedule();
|
||||||
|
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
|
return -ERESTARTNOHAND;
|
||||||
|
}
|
||||||
|
#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
|
||||||
|
|
||||||
void __init signals_init(void)
|
void __init signals_init(void)
|
||||||
{
|
{
|
||||||
sigqueue_cachep =
|
sigqueue_cachep =
|
||||||
|
|
Загрузка…
Ссылка в новой задаче