diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2016-07-04 05:50:25 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-07-07 04:35:07 -0400 |
commit | 2b1ecc3d1a6b10f8fbac7f83d80db30b5a2c2791 (patch) | |
tree | a315e58fe3cf5a94f6ca990fb65d2a57834a7fc7 /kernel/signal.c | |
parent | 177ec0a0a531695210b277d734b2f92ee5796303 (diff) |
signals: Use hrtimer for sigtimedwait()
We've converted most timeout related syscalls to hrtimers, but
sigtimedwait() did not get this treatment.
Convert it so we get a reasonable accuracy and remove the
user space exposure to the timer wheel properties.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Arjan van de Ven <arjan@infradead.org>
Cc: Chris Mason <clm@fb.com>
Cc: Cyril Hrubis <chrubis@suse.cz>
Cc: George Spelvin <linux@sciencehorizons.net>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Len Brown <lenb@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: rt@linutronix.de
Link: http://lkml.kernel.org/r/20160704094341.787164909@linutronix.de
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 24 |
1 files changed, 10 insertions, 14 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 96e9bc40667f..af21afc00d08 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -2751,23 +2751,18 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from) | |||
2751 | * @ts: upper bound on process time suspension | 2751 | * @ts: upper bound on process time suspension |
2752 | */ | 2752 | */ |
2753 | int do_sigtimedwait(const sigset_t *which, siginfo_t *info, | 2753 | int do_sigtimedwait(const sigset_t *which, siginfo_t *info, |
2754 | const struct timespec *ts) | 2754 | const struct timespec *ts) |
2755 | { | 2755 | { |
2756 | ktime_t *to = NULL, timeout = { .tv64 = KTIME_MAX }; | ||
2756 | struct task_struct *tsk = current; | 2757 | struct task_struct *tsk = current; |
2757 | long timeout = MAX_SCHEDULE_TIMEOUT; | ||
2758 | sigset_t mask = *which; | 2758 | sigset_t mask = *which; |
2759 | int sig; | 2759 | int sig, ret = 0; |
2760 | 2760 | ||
2761 | if (ts) { | 2761 | if (ts) { |
2762 | if (!timespec_valid(ts)) | 2762 | if (!timespec_valid(ts)) |
2763 | return -EINVAL; | 2763 | return -EINVAL; |
2764 | timeout = timespec_to_jiffies(ts); | 2764 | timeout = timespec_to_ktime(*ts); |
2765 | /* | 2765 | to = &timeout; |
2766 | * We can be close to the next tick, add another one | ||
2767 | * to ensure we will wait at least the time asked for. | ||
2768 | */ | ||
2769 | if (ts->tv_sec || ts->tv_nsec) | ||
2770 | timeout++; | ||
2771 | } | 2766 | } |
2772 | 2767 | ||
2773 | /* | 2768 | /* |
@@ -2778,7 +2773,7 @@ int do_sigtimedwait(const sigset_t *which, siginfo_t *info, | |||
2778 | 2773 | ||
2779 | spin_lock_irq(&tsk->sighand->siglock); | 2774 | spin_lock_irq(&tsk->sighand->siglock); |
2780 | sig = dequeue_signal(tsk, &mask, info); | 2775 | sig = dequeue_signal(tsk, &mask, info); |
2781 | if (!sig && timeout) { | 2776 | if (!sig && timeout.tv64) { |
2782 | /* | 2777 | /* |
2783 | * None ready, temporarily unblock those we're interested | 2778 | * None ready, temporarily unblock those we're interested |
2784 | * while we are sleeping in so that we'll be awakened when | 2779 | * while we are sleeping in so that we'll be awakened when |
@@ -2790,8 +2785,9 @@ int do_sigtimedwait(const sigset_t *which, siginfo_t *info, | |||
2790 | recalc_sigpending(); | 2785 | recalc_sigpending(); |
2791 | spin_unlock_irq(&tsk->sighand->siglock); | 2786 | spin_unlock_irq(&tsk->sighand->siglock); |
2792 | 2787 | ||
2793 | timeout = freezable_schedule_timeout_interruptible(timeout); | 2788 | __set_current_state(TASK_INTERRUPTIBLE); |
2794 | 2789 | ret = freezable_schedule_hrtimeout_range(to, tsk->timer_slack_ns, | |
2790 | HRTIMER_MODE_REL); | ||
2795 | spin_lock_irq(&tsk->sighand->siglock); | 2791 | spin_lock_irq(&tsk->sighand->siglock); |
2796 | __set_task_blocked(tsk, &tsk->real_blocked); | 2792 | __set_task_blocked(tsk, &tsk->real_blocked); |
2797 | sigemptyset(&tsk->real_blocked); | 2793 | sigemptyset(&tsk->real_blocked); |
@@ -2801,7 +2797,7 @@ int do_sigtimedwait(const sigset_t *which, siginfo_t *info, | |||
2801 | 2797 | ||
2802 | if (sig) | 2798 | if (sig) |
2803 | return sig; | 2799 | return sig; |
2804 | return timeout ? -EINTR : -EAGAIN; | 2800 | return ret ? -EINTR : -EAGAIN; |
2805 | } | 2801 | } |
2806 | 2802 | ||
2807 | /** | 2803 | /** |