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 | |
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')
-rw-r--r-- | kernel/compat.c | 42 | ||||
-rw-r--r-- | kernel/signal.c | 48 |
2 files changed, 39 insertions, 51 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index 38b1d2c1cbe8..06cbb0619531 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -893,7 +893,7 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | |||
893 | int sig; | 893 | int sig; |
894 | struct timespec t; | 894 | struct timespec t; |
895 | siginfo_t info; | 895 | siginfo_t info; |
896 | long ret, timeout = 0; | 896 | long ret, timeout; |
897 | 897 | ||
898 | if (sigsetsize != sizeof(sigset_t)) | 898 | if (sigsetsize != sizeof(sigset_t)) |
899 | return -EINVAL; | 899 | return -EINVAL; |
@@ -904,36 +904,30 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | |||
904 | sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP)); | 904 | sigdelsetmask(&s,sigmask(SIGKILL)|sigmask(SIGSTOP)); |
905 | signotset(&s); | 905 | signotset(&s); |
906 | 906 | ||
907 | timeout = MAX_SCHEDULE_TIMEOUT; | ||
907 | if (uts) { | 908 | if (uts) { |
908 | if (get_compat_timespec (&t, uts)) | 909 | if (get_compat_timespec (&t, uts)) |
909 | return -EFAULT; | 910 | return -EFAULT; |
910 | if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0 | 911 | if (!timespec_valid(&t)) |
911 | || t.tv_sec < 0) | ||
912 | return -EINVAL; | 912 | return -EINVAL; |
913 | timeout = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec); | ||
913 | } | 914 | } |
914 | 915 | ||
915 | spin_lock_irq(¤t->sighand->siglock); | 916 | spin_lock_irq(¤t->sighand->siglock); |
916 | sig = dequeue_signal(current, &s, &info); | 917 | sig = dequeue_signal(current, &s, &info); |
917 | if (!sig) { | 918 | if (!sig && timeout) { |
918 | timeout = MAX_SCHEDULE_TIMEOUT; | 919 | current->real_blocked = current->blocked; |
919 | if (uts) | 920 | sigandsets(¤t->blocked, ¤t->blocked, &s); |
920 | timeout = timespec_to_jiffies(&t) | 921 | recalc_sigpending(); |
921 | +(t.tv_sec || t.tv_nsec); | 922 | spin_unlock_irq(¤t->sighand->siglock); |
922 | if (timeout) { | 923 | |
923 | current->real_blocked = current->blocked; | 924 | timeout = schedule_timeout_interruptible(timeout); |
924 | sigandsets(¤t->blocked, ¤t->blocked, &s); | 925 | |
925 | 926 | spin_lock_irq(¤t->sighand->siglock); | |
926 | recalc_sigpending(); | 927 | sig = dequeue_signal(current, &s, &info); |
927 | spin_unlock_irq(¤t->sighand->siglock); | 928 | current->blocked = current->real_blocked; |
928 | 929 | siginitset(¤t->real_blocked, 0); | |
929 | timeout = schedule_timeout_interruptible(timeout); | 930 | recalc_sigpending(); |
930 | |||
931 | spin_lock_irq(¤t->sighand->siglock); | ||
932 | sig = dequeue_signal(current, &s, &info); | ||
933 | current->blocked = current->real_blocked; | ||
934 | siginitset(¤t->real_blocked, 0); | ||
935 | recalc_sigpending(); | ||
936 | } | ||
937 | } | 931 | } |
938 | spin_unlock_irq(¤t->sighand->siglock); | 932 | spin_unlock_irq(¤t->sighand->siglock); |
939 | 933 | ||
@@ -943,7 +937,7 @@ compat_sys_rt_sigtimedwait (compat_sigset_t __user *uthese, | |||
943 | if (copy_siginfo_to_user32(uinfo, &info)) | 937 | if (copy_siginfo_to_user32(uinfo, &info)) |
944 | ret = -EFAULT; | 938 | ret = -EFAULT; |
945 | } | 939 | } |
946 | }else { | 940 | } else { |
947 | ret = timeout?-EINTR:-EAGAIN; | 941 | ret = timeout?-EINTR:-EAGAIN; |
948 | } | 942 | } |
949 | return ret; | 943 | return ret; |
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 | ||