diff options
author | Oleg Nesterov <oleg@redhat.com> | 2011-04-27 15:24:19 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2011-04-28 07:01:38 -0400 |
commit | fe0faa005d43bc44c357631d51c273806086caa4 (patch) | |
tree | 7977c5ec7c452ed3a0036747b8d8861b742c30b3 /kernel/signal.c | |
parent | bb7efee2ca63b08795ffb3cda96fc89d2e641b79 (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.c | 48 |
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(¤t->sighand->siglock); | 2547 | spin_lock_irq(¤t->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(¤t->blocked, ¤t->blocked, &these); | ||
2557 | recalc_sigpending(); | ||
2558 | spin_unlock_irq(¤t->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(¤t->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(¤t->real_blocked, 0); |
2560 | current->real_blocked = current->blocked; | 2566 | recalc_sigpending(); |
2561 | sigandsets(¤t->blocked, ¤t->blocked, &these); | ||
2562 | recalc_sigpending(); | ||
2563 | spin_unlock_irq(¤t->sighand->siglock); | ||
2564 | |||
2565 | timeout = schedule_timeout_interruptible(timeout); | ||
2566 | |||
2567 | spin_lock_irq(¤t->sighand->siglock); | ||
2568 | sig = dequeue_signal(current, &these, &info); | ||
2569 | current->blocked = current->real_blocked; | ||
2570 | siginitset(¤t->real_blocked, 0); | ||
2571 | recalc_sigpending(); | ||
2572 | } | ||
2573 | } | 2567 | } |
2574 | spin_unlock_irq(¤t->sighand->siglock); | 2568 | spin_unlock_irq(¤t->sighand->siglock); |
2575 | 2569 | ||