sched/wait: Fix a kthread_park race with wait_woken()
authorArve Hjønnevåg <arve@android.com>
Fri, 2 Jun 2023 21:23:46 +0000 (21:23 +0000)
committerPeter Zijlstra <peterz@infradead.org>
Fri, 16 Jun 2023 15:08:01 +0000 (17:08 +0200)
kthread_park and wait_woken have a similar race that
kthread_stop and wait_woken used to have before it was fixed in
commit cb6538e740d7 ("sched/wait: Fix a kthread race with
wait_woken()"). Extend that fix to also cover kthread_park.

[jstultz: Made changes suggested by Peter to optimize
 memory loads]

Signed-off-by: Arve Hjønnevåg <arve@android.com>
Signed-off-by: John Stultz <jstultz@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Valentin Schneider <vschneid@redhat.com>
Link: https://lore.kernel.org/r/20230602212350.535358-1-jstultz@google.com
include/linux/kthread.h
kernel/kthread.c
kernel/sched/wait.c

index 30e5bec81d2b6246c4cfdb6ef0aecfb46f046e2b..f1f95a71a4bcb2bbb34e1587c7dc7f0d661a6003 100644 (file)
@@ -89,6 +89,7 @@ int kthread_stop(struct task_struct *k);
 bool kthread_should_stop(void);
 bool kthread_should_park(void);
 bool __kthread_should_park(struct task_struct *k);
+bool kthread_should_stop_or_park(void);
 bool kthread_freezable_should_stop(bool *was_frozen);
 void *kthread_func(struct task_struct *k);
 void *kthread_data(struct task_struct *k);
index 490792b1066ec30ba8fe336243d51cc76536b8a1..07a057086d26b428af731d6fbc8aa829fa05eeb5 100644 (file)
@@ -182,6 +182,16 @@ bool kthread_should_park(void)
 }
 EXPORT_SYMBOL_GPL(kthread_should_park);
 
+bool kthread_should_stop_or_park(void)
+{
+       struct kthread *kthread = __to_kthread(current);
+
+       if (!kthread)
+               return false;
+
+       return kthread->flags & (BIT(KTHREAD_SHOULD_STOP) | BIT(KTHREAD_SHOULD_PARK));
+}
+
 /**
  * kthread_freezable_should_stop - should this freezable kthread return now?
  * @was_frozen: optional out parameter, indicates whether %current was frozen
index 133b74730738bef2c412d6b270fddb3944b4b22c..48c53e4739ea4ea367078250ce3bbf694991e548 100644 (file)
@@ -425,11 +425,6 @@ int autoremove_wake_function(struct wait_queue_entry *wq_entry, unsigned mode, i
 }
 EXPORT_SYMBOL(autoremove_wake_function);
 
-static inline bool is_kthread_should_stop(void)
-{
-       return (current->flags & PF_KTHREAD) && kthread_should_stop();
-}
-
 /*
  * DEFINE_WAIT_FUNC(wait, woken_wake_func);
  *
@@ -459,7 +454,7 @@ long wait_woken(struct wait_queue_entry *wq_entry, unsigned mode, long timeout)
         * or woken_wake_function() sees our store to current->state.
         */
        set_current_state(mode); /* A */
-       if (!(wq_entry->flags & WQ_FLAG_WOKEN) && !is_kthread_should_stop())
+       if (!(wq_entry->flags & WQ_FLAG_WOKEN) && !kthread_should_stop_or_park())
                timeout = schedule_timeout(timeout);
        __set_current_state(TASK_RUNNING);