diff options
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 26 |
1 files changed, 26 insertions, 0 deletions
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 | ||
2725 | asmlinkage 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(¤t->sighand->siglock); | ||
2738 | current->saved_sigmask = current->blocked; | ||
2739 | current->blocked = newset; | ||
2740 | recalc_sigpending(); | ||
2741 | spin_unlock_irq(¤t->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 | |||
2724 | void __init signals_init(void) | 2750 | void __init signals_init(void) |
2725 | { | 2751 | { |
2726 | sigqueue_cachep = | 2752 | sigqueue_cachep = |