From 9cd956207af8d33ed94d04f5da3094abe522da4a Mon Sep 17 00:00:00 2001 Message-Id: <9cd956207af8d33ed94d04f5da3094abe522da4a.1601675152.git.zanussi@kernel.org> In-Reply-To: <5b5a156f9808b1acf1205606e03da117214549ea.1601675151.git.zanussi@kernel.org> References: <5b5a156f9808b1acf1205606e03da117214549ea.1601675151.git.zanussi@kernel.org> From: Sebastian Andrzej Siewior Date: Thu, 6 Dec 2018 10:15:13 +0100 Subject: [PATCH 103/333] 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.148-rt64.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 Signed-off-by: Sebastian Andrzej Siewior --- 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.17.1