aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2011-04-27 15:24:19 -0400
committerOleg Nesterov <oleg@redhat.com>2011-04-28 07:01:38 -0400
commitfe0faa005d43bc44c357631d51c273806086caa4 (patch)
tree7977c5ec7c452ed3a0036747b8d8861b742c30b3 /kernel/signal.c
parentbb7efee2ca63b08795ffb3cda96fc89d2e641b79 (diff)
signal: sys_rt_sigtimedwait: simplify the timeout logic
No functional changes, cleanup compat_sys_rt_sigtimedwait() and sys_rt_sigtimedwait(). Calculate the timeout before we take ->siglock, this simplifies and lessens the code. Use timespec_valid() to check the timespec. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Tejun Heo <tj@kernel.org> Reviewed-by: Matt Fleming <matt.fleming@linux.intel.com>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c48
1 files changed, 21 insertions, 27 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index bb9200070ea0..c734619554f6 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2519,7 +2519,7 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
2519 sigset_t these; 2519 sigset_t these;
2520 struct timespec ts; 2520 struct timespec ts;
2521 siginfo_t info; 2521 siginfo_t info;
2522 long timeout = 0; 2522 long timeout;
2523 2523
2524 /* XXX: Don't preclude handling different sized sigset_t's. */ 2524 /* XXX: Don't preclude handling different sized sigset_t's. */
2525 if (sigsetsize != sizeof(sigset_t)) 2525 if (sigsetsize != sizeof(sigset_t))
@@ -2535,41 +2535,35 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
2535 sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP)); 2535 sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
2536 signotset(&these); 2536 signotset(&these);
2537 2537
2538 timeout = MAX_SCHEDULE_TIMEOUT;
2538 if (uts) { 2539 if (uts) {
2539 if (copy_from_user(&ts, uts, sizeof(ts))) 2540 if (copy_from_user(&ts, uts, sizeof(ts)))
2540 return -EFAULT; 2541 return -EFAULT;
2541 if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0 2542 if (!timespec_valid(&ts))
2542 || ts.tv_sec < 0)
2543 return -EINVAL; 2543 return -EINVAL;
2544 timeout = timespec_to_jiffies(&ts) + (ts.tv_sec || ts.tv_nsec);
2544 } 2545 }
2545 2546
2546 spin_lock_irq(&current->sighand->siglock); 2547 spin_lock_irq(&current->sighand->siglock);
2547 sig = dequeue_signal(current, &these, &info); 2548 sig = dequeue_signal(current, &these, &info);
2548 if (!sig) { 2549 if (!sig && timeout) {
2549 timeout = MAX_SCHEDULE_TIMEOUT; 2550 /*
2550 if (uts) 2551 * None ready -- temporarily unblock those we're
2551 timeout = (timespec_to_jiffies(&ts) 2552 * interested while we are sleeping in so that we'll
2552 + (ts.tv_sec || ts.tv_nsec)); 2553 * be awakened when they arrive.
2554 */
2555 current->real_blocked = current->blocked;
2556 sigandsets(&current->blocked, &current->blocked, &these);
2557 recalc_sigpending();
2558 spin_unlock_irq(&current->sighand->siglock);
2553 2559
2554 if (timeout) { 2560 timeout = schedule_timeout_interruptible(timeout);
2555 /* 2561
2556 * None ready -- temporarily unblock those we're 2562 spin_lock_irq(&current->sighand->siglock);
2557 * interested while we are sleeping in so that we'll 2563 sig = dequeue_signal(current, &these, &info);
2558 * be awakened when they arrive. 2564 current->blocked = current->real_blocked;
2559 */ 2565 siginitset(&current->real_blocked, 0);
2560 current->real_blocked = current->blocked; 2566 recalc_sigpending();
2561 sigandsets(&current->blocked, &current->blocked, &these);
2562 recalc_sigpending();
2563 spin_unlock_irq(&current->sighand->siglock);
2564
2565 timeout = schedule_timeout_interruptible(timeout);
2566
2567 spin_lock_irq(&current->sighand->siglock);
2568 sig = dequeue_signal(current, &these, &info);
2569 current->blocked = current->real_blocked;
2570 siginitset(&current->real_blocked, 0);
2571 recalc_sigpending();
2572 }
2573 } 2567 }
2574 spin_unlock_irq(&current->sighand->siglock); 2568 spin_unlock_irq(&current->sighand->siglock);
2575 2569