52 lines
1.9 KiB
Diff
52 lines
1.9 KiB
Diff
From 6b0b0a70d8daac88d3492deb4dfa74c7e232fa8e Mon Sep 17 00:00:00 2001
|
|
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
Date: Thu, 6 Dec 2018 10:15:13 +0100
|
|
Subject: [PATCH 103/325] hrtimer: move state change before hrtimer_cancel in
|
|
do_nanosleep()
|
|
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.115-rt48.tar.xz
|
|
|
|
There is a small window between setting t->task to NULL and waking the
|
|
task up (which would set TASK_RUNNING). So the timer would fire, run and
|
|
set ->task to NULL while the other side/do_nanosleep() wouldn't enter
|
|
freezable_schedule(). After all we are peemptible here (in
|
|
do_nanosleep() and on the timer wake up path) and on KVM/virt the
|
|
virt-CPU might get preempted.
|
|
So do_nanosleep() wouldn't enter freezable_schedule() but cancel the
|
|
timer which is still running and wait for it via
|
|
hrtimer_wait_for_timer(). Then wait_event()/might_sleep() would complain
|
|
that it is invoked with state != TASK_RUNNING.
|
|
This isn't a problem since it would be reset to TASK_RUNNING later
|
|
anyway and we don't rely on the previous state.
|
|
|
|
Move the state update to TASK_RUNNING before hrtimer_cancel() so there
|
|
are no complains from might_sleep() about wrong state.
|
|
|
|
Cc: stable-rt@vger.kernel.org
|
|
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
|
|
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
|
|
---
|
|
kernel/time/hrtimer.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
|
|
index 9f3412acdb16..b800efb64238 100644
|
|
--- a/kernel/time/hrtimer.c
|
|
+++ b/kernel/time/hrtimer.c
|
|
@@ -1788,12 +1788,12 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
|
|
if (likely(t->task))
|
|
freezable_schedule();
|
|
|
|
+ __set_current_state(TASK_RUNNING);
|
|
hrtimer_cancel(&t->timer);
|
|
mode = HRTIMER_MODE_ABS;
|
|
|
|
} while (t->task && !signal_pending(current));
|
|
|
|
- __set_current_state(TASK_RUNNING);
|
|
|
|
if (!t->task)
|
|
return 0;
|
|
--
|
|
2.25.1
|
|
|