[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.
|
||||
*/
|
||||
long sys_sigsuspend(old_sigset_t mask, int p2, int p3, int p4, int p6, int p7,
|
||||
struct pt_regs *regs)
|
||||
long sys_sigsuspend(old_sigset_t mask)
|
||||
{
|
||||
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();
|
||||
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_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;
|
||||
}
|
||||
}
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
|
|
|
@ -67,42 +67,6 @@ struct rt_sigframe {
|
|||
char abigap[288];
|
||||
} __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,
|
||||
unsigned long r6, unsigned long r7, unsigned long r8,
|
||||
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_SIGPROCMASK
|
||||
#define __ARCH_WANT_SYS_RT_SIGACTION
|
||||
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
#ifdef CONFIG_PPC32
|
||||
#define __ARCH_WANT_OLD_STAT
|
||||
#endif
|
||||
#ifdef CONFIG_PPC64
|
||||
#define __ARCH_WANT_COMPAT_SYS_TIME
|
||||
#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
|
|
@ -809,6 +809,7 @@ struct task_struct {
|
|||
struct sighand_struct *sighand;
|
||||
|
||||
sigset_t blocked, real_blocked;
|
||||
sigset_t saved_sigmask; /* To be restored with TIF_RESTORE_SIGMASK */
|
||||
struct sigpending pending;
|
||||
|
||||
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 */
|
||||
|
||||
#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
|
||||
|
||||
#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)
|
||||
{
|
||||
sigqueue_cachep =
|
||||
|
|
Загрузка…
Ссылка в новой задаче