sched/wait: Fix a kthread_park race with wait_woken()
kthread_park and wait_woken have a similar race that
kthread_stop and wait_woken used to have before it was fixed in
commit cb6538e740
("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
This commit is contained in:
parent
0cce0fde49
commit
ef73d6a4ef
|
@ -89,6 +89,7 @@ int kthread_stop(struct task_struct *k);
|
||||||
bool kthread_should_stop(void);
|
bool kthread_should_stop(void);
|
||||||
bool kthread_should_park(void);
|
bool kthread_should_park(void);
|
||||||
bool __kthread_should_park(struct task_struct *k);
|
bool __kthread_should_park(struct task_struct *k);
|
||||||
|
bool kthread_should_stop_or_park(void);
|
||||||
bool kthread_freezable_should_stop(bool *was_frozen);
|
bool kthread_freezable_should_stop(bool *was_frozen);
|
||||||
void *kthread_func(struct task_struct *k);
|
void *kthread_func(struct task_struct *k);
|
||||||
void *kthread_data(struct task_struct *k);
|
void *kthread_data(struct task_struct *k);
|
||||||
|
|
|
@ -182,6 +182,16 @@ bool kthread_should_park(void)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kthread_should_park);
|
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?
|
* kthread_freezable_should_stop - should this freezable kthread return now?
|
||||||
* @was_frozen: optional out parameter, indicates whether %current was frozen
|
* @was_frozen: optional out parameter, indicates whether %current was frozen
|
||||||
|
|
|
@ -425,11 +425,6 @@ int autoremove_wake_function(struct wait_queue_entry *wq_entry, unsigned mode, i
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(autoremove_wake_function);
|
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);
|
* 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.
|
* or woken_wake_function() sees our store to current->state.
|
||||||
*/
|
*/
|
||||||
set_current_state(mode); /* A */
|
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);
|
timeout = schedule_timeout(timeout);
|
||||||
__set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue