summaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2016-07-04 05:50:25 -0400
committerIngo Molnar <mingo@kernel.org>2016-07-07 04:35:07 -0400
commit2b1ecc3d1a6b10f8fbac7f83d80db30b5a2c2791 (patch)
treea315e58fe3cf5a94f6ca990fb65d2a57834a7fc7 /kernel/signal.c
parent177ec0a0a531695210b277d734b2f92ee5796303 (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.c24
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 */
2753int do_sigtimedwait(const sigset_t *which, siginfo_t *info, 2753int 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/**