2019-05-19 15:08:55 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2012-04-20 17:05:44 +04:00
/*
* Common SMP CPU bringup / teardown functions
*/
2012-07-16 14:42:36 +04:00
# include <linux/cpu.h>
2012-04-20 17:05:45 +04:00
# include <linux/err.h>
# include <linux/smp.h>
smpboot: Add common code for notification from dying CPU
RCU ignores offlined CPUs, so they cannot safely run RCU read-side code.
(They -can- use SRCU, but not RCU.) This means that any use of RCU
during or after the call to arch_cpu_idle_dead(). Unfortunately,
commit 2ed53c0d6cc99 added a complete() call, which will contain RCU
read-side critical sections if there is a task waiting to be awakened.
Which, as it turns out, there almost never is. In my qemu/KVM testing,
the to-be-awakened task is not yet asleep more than 99.5% of the time.
In current mainline, failure is even harder to reproduce, requiring a
virtualized environment that delays the outgoing CPU by at least three
jiffies between the time it exits its stop_machine() task at CPU_DYING
time and the time it calls arch_cpu_idle_dead() from the idle loop.
However, this problem really can occur, especially in virtualized
environments, and therefore really does need to be fixed
This suggests moving back to the polling loop, but using a much shorter
wait, with gentle exponential backoff instead of the old 100-millisecond
wait. Most of the time, the loop will exit without waiting at all,
and almost all of the remaining uses will wait only five microseconds.
If the outgoing CPU is preempted, a loop will wait one jiffy, then
increase the wait by a factor of 11/10ths, rounding up. As before, there
is a five-second timeout.
This commit therefore provides common-code infrastructure to do the
dying-to-surviving CPU handoff in a safe manner. This code also
provides an indication at CPU-online of whether the CPU to be onlined
previously timed out on offline. The new cpu_check_up_prepare() function
returns -EBUSY if this CPU previously took more than five seconds to
go offline, or -EAGAIN if it has not yet managed to go offline. The
rationale for -EAGAIN is that it might still be preempted, so an additional
wait might well find it correctly offlined. Architecture-specific code
can decide how to handle these conditions. Systems in which CPUs take
themselves completely offline might respond to an -EBUSY return as if
it was a zero (success) return. Systems in which the surviving CPU must
take some action might take it at this time, or might simply mark the
other CPU as unusable.
Note that architectures that take the easy way out and simply pass the
-EBUSY and -EAGAIN upwards will change the sysfs API.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: <linux-api@vger.kernel.org>
Cc: <linux-arch@vger.kernel.org>
[ paulmck: Fixed state machine for architectures that don't check earlier
CPU-hotplug results as suggested by James Hogan. ]
2015-02-25 21:34:39 +03:00
# include <linux/delay.h>
2012-04-20 17:05:44 +04:00
# include <linux/init.h>
2012-07-16 14:42:36 +04:00
# include <linux/list.h>
# include <linux/slab.h>
2012-04-20 17:05:45 +04:00
# include <linux/sched.h>
2017-02-08 20:51:36 +03:00
# include <linux/sched/task.h>
2012-07-16 14:42:36 +04:00
# include <linux/export.h>
2012-04-20 17:05:45 +04:00
# include <linux/percpu.h>
2012-07-16 14:42:36 +04:00
# include <linux/kthread.h>
# include <linux/smpboot.h>
2012-04-20 17:05:44 +04:00
# include "smpboot.h"
2012-07-12 12:55:54 +04:00
# ifdef CONFIG_SMP
2012-04-20 17:05:45 +04:00
# ifdef CONFIG_GENERIC_SMP_IDLE_THREAD
/*
* For the hotplug case we keep the task structs around and reuse
* them .
*/
static DEFINE_PER_CPU ( struct task_struct * , idle_threads ) ;
2013-06-19 22:53:51 +04:00
struct task_struct * idle_thread_get ( unsigned int cpu )
2012-04-20 17:05:45 +04:00
{
struct task_struct * tsk = per_cpu ( idle_threads , cpu ) ;
if ( ! tsk )
2012-04-21 04:08:50 +04:00
return ERR_PTR ( - ENOMEM ) ;
2012-04-20 17:05:45 +04:00
return tsk ;
}
2012-04-21 04:08:50 +04:00
void __init idle_thread_set_boot_cpu ( void )
2012-04-20 17:05:45 +04:00
{
2012-04-21 04:08:50 +04:00
per_cpu ( idle_threads , smp_processor_id ( ) ) = current ;
2012-04-20 17:05:45 +04:00
}
2012-05-24 19:11:00 +04:00
/**
* idle_init - Initialize the idle thread for a cpu
* @ cpu : The cpu for which the idle thread should be initialized
*
* Creates the thread if it does not exist .
*/
2021-07-25 21:06:37 +03:00
static __always_inline void idle_init ( unsigned int cpu )
2012-04-20 17:05:45 +04:00
{
2012-04-21 04:08:50 +04:00
struct task_struct * tsk = per_cpu ( idle_threads , cpu ) ;
if ( ! tsk ) {
tsk = fork_idle ( cpu ) ;
if ( IS_ERR ( tsk ) )
pr_err ( " SMP: fork_idle() failed for CPU %u \n " , cpu ) ;
else
per_cpu ( idle_threads , cpu ) = tsk ;
}
2012-04-20 17:05:45 +04:00
}
/**
2012-05-24 19:11:00 +04:00
* idle_threads_init - Initialize idle threads for all cpus
2012-04-20 17:05:45 +04:00
*/
2012-04-21 04:08:50 +04:00
void __init idle_threads_init ( void )
2012-04-20 17:05:45 +04:00
{
2012-05-24 19:10:55 +04:00
unsigned int cpu , boot_cpu ;
boot_cpu = smp_processor_id ( ) ;
2012-04-20 17:05:45 +04:00
2012-04-21 04:08:50 +04:00
for_each_possible_cpu ( cpu ) {
2012-05-24 19:10:55 +04:00
if ( cpu ! = boot_cpu )
2012-04-21 04:08:50 +04:00
idle_init ( cpu ) ;
2012-04-20 17:05:45 +04:00
}
}
# endif
2012-07-16 14:42:36 +04:00
2012-07-12 12:55:54 +04:00
# endif /* #ifdef CONFIG_SMP */
2012-07-16 14:42:36 +04:00
static LIST_HEAD ( hotplug_threads ) ;
static DEFINE_MUTEX ( smpboot_threads_lock ) ;
struct smpboot_thread_data {
unsigned int cpu ;
unsigned int status ;
struct smp_hotplug_thread * ht ;
} ;
enum {
HP_THREAD_NONE = 0 ,
HP_THREAD_ACTIVE ,
HP_THREAD_PARKED ,
} ;
/**
* smpboot_thread_fn - percpu hotplug thread loop function
* @ data : thread data pointer
*
* Checks for thread stop and park conditions . Calls the necessary
* setup , cleanup , park and unpark functions for the registered
* thread .
*
* Returns 1 when the thread should exit , 0 otherwise .
*/
static int smpboot_thread_fn ( void * data )
{
struct smpboot_thread_data * td = data ;
struct smp_hotplug_thread * ht = td - > ht ;
while ( 1 ) {
set_current_state ( TASK_INTERRUPTIBLE ) ;
preempt_disable ( ) ;
if ( kthread_should_stop ( ) ) {
2014-09-24 12:18:52 +04:00
__set_current_state ( TASK_RUNNING ) ;
2012-07-16 14:42:36 +04:00
preempt_enable ( ) ;
2015-09-05 01:45:03 +03:00
/* cleanup must mirror setup */
if ( ht - > cleanup & & td - > status ! = HP_THREAD_NONE )
2012-07-16 14:42:36 +04:00
ht - > cleanup ( td - > cpu , cpu_online ( td - > cpu ) ) ;
kfree ( td ) ;
return 0 ;
}
if ( kthread_should_park ( ) ) {
__set_current_state ( TASK_RUNNING ) ;
2016-10-04 10:55:57 +03:00
preempt_enable ( ) ;
2012-07-16 14:42:36 +04:00
if ( ht - > park & & td - > status = = HP_THREAD_ACTIVE ) {
BUG_ON ( td - > cpu ! = smp_processor_id ( ) ) ;
ht - > park ( td - > cpu ) ;
td - > status = HP_THREAD_PARKED ;
}
kthread_parkme ( ) ;
/* We might have been woken for stop */
continue ;
}
2013-03-09 00:43:31 +04:00
BUG_ON ( td - > cpu ! = smp_processor_id ( ) ) ;
2012-07-16 14:42:36 +04:00
/* Check for state change setup */
switch ( td - > status ) {
case HP_THREAD_NONE :
2014-09-24 12:18:52 +04:00
__set_current_state ( TASK_RUNNING ) ;
2012-07-16 14:42:36 +04:00
preempt_enable ( ) ;
if ( ht - > setup )
ht - > setup ( td - > cpu ) ;
td - > status = HP_THREAD_ACTIVE ;
2014-09-24 12:18:52 +04:00
continue ;
2012-07-16 14:42:36 +04:00
case HP_THREAD_PARKED :
2014-09-24 12:18:52 +04:00
__set_current_state ( TASK_RUNNING ) ;
2012-07-16 14:42:36 +04:00
preempt_enable ( ) ;
if ( ht - > unpark )
ht - > unpark ( td - > cpu ) ;
td - > status = HP_THREAD_ACTIVE ;
2014-09-24 12:18:52 +04:00
continue ;
2012-07-16 14:42:36 +04:00
}
if ( ! ht - > thread_should_run ( td - > cpu ) ) {
2014-09-24 12:18:52 +04:00
preempt_enable_no_resched ( ) ;
2012-07-16 14:42:36 +04:00
schedule ( ) ;
} else {
2014-09-24 12:18:52 +04:00
__set_current_state ( TASK_RUNNING ) ;
2012-07-16 14:42:36 +04:00
preempt_enable ( ) ;
ht - > thread_fn ( td - > cpu ) ;
}
}
}
static int
__smpboot_create_thread ( struct smp_hotplug_thread * ht , unsigned int cpu )
{
struct task_struct * tsk = * per_cpu_ptr ( ht - > store , cpu ) ;
struct smpboot_thread_data * td ;
if ( tsk )
return 0 ;
td = kzalloc_node ( sizeof ( * td ) , GFP_KERNEL , cpu_to_node ( cpu ) ) ;
if ( ! td )
return - ENOMEM ;
td - > cpu = cpu ;
td - > ht = ht ;
tsk = kthread_create_on_cpu ( smpboot_thread_fn , td , cpu ,
ht - > thread_comm ) ;
if ( IS_ERR ( tsk ) ) {
kfree ( td ) ;
return PTR_ERR ( tsk ) ;
}
2021-01-12 13:24:04 +03:00
kthread_set_per_cpu ( tsk , cpu ) ;
2016-10-11 23:55:23 +03:00
/*
* Park the thread so that it could start right on the CPU
* when it is available .
*/
kthread_park ( tsk ) ;
2012-07-16 14:42:36 +04:00
get_task_struct ( tsk ) ;
* per_cpu_ptr ( ht - > store , cpu ) = tsk ;
2013-04-09 11:33:34 +04:00
if ( ht - > create ) {
/*
* Make sure that the task has actually scheduled out
* into park position , before calling the create
* callback . At least the migration thread callback
* requires that the task is off the runqueue .
*/
if ( ! wait_task_inactive ( tsk , TASK_PARKED ) )
WARN_ON ( 1 ) ;
else
ht - > create ( cpu ) ;
}
2012-07-16 14:42:36 +04:00
return 0 ;
}
int smpboot_create_threads ( unsigned int cpu )
{
struct smp_hotplug_thread * cur ;
int ret = 0 ;
mutex_lock ( & smpboot_threads_lock ) ;
list_for_each_entry ( cur , & hotplug_threads , list ) {
ret = __smpboot_create_thread ( cur , cpu ) ;
if ( ret )
break ;
}
mutex_unlock ( & smpboot_threads_lock ) ;
return ret ;
}
static void smpboot_unpark_thread ( struct smp_hotplug_thread * ht , unsigned int cpu )
{
struct task_struct * tsk = * per_cpu_ptr ( ht - > store , cpu ) ;
2015-10-09 19:00:49 +03:00
if ( ! ht - > selfparking )
kthread_unpark ( tsk ) ;
2012-07-16 14:42:36 +04:00
}
2016-02-26 21:43:36 +03:00
int smpboot_unpark_threads ( unsigned int cpu )
2012-07-16 14:42:36 +04:00
{
struct smp_hotplug_thread * cur ;
mutex_lock ( & smpboot_threads_lock ) ;
list_for_each_entry ( cur , & hotplug_threads , list )
2018-06-07 11:53:01 +03:00
smpboot_unpark_thread ( cur , cpu ) ;
2012-07-16 14:42:36 +04:00
mutex_unlock ( & smpboot_threads_lock ) ;
2016-02-26 21:43:36 +03:00
return 0 ;
2012-07-16 14:42:36 +04:00
}
static void smpboot_park_thread ( struct smp_hotplug_thread * ht , unsigned int cpu )
{
struct task_struct * tsk = * per_cpu_ptr ( ht - > store , cpu ) ;
2013-01-31 16:11:12 +04:00
if ( tsk & & ! ht - > selfparking )
2012-07-16 14:42:36 +04:00
kthread_park ( tsk ) ;
}
2016-02-26 21:43:36 +03:00
int smpboot_park_threads ( unsigned int cpu )
2012-07-16 14:42:36 +04:00
{
struct smp_hotplug_thread * cur ;
mutex_lock ( & smpboot_threads_lock ) ;
list_for_each_entry_reverse ( cur , & hotplug_threads , list )
smpboot_park_thread ( cur , cpu ) ;
mutex_unlock ( & smpboot_threads_lock ) ;
2016-02-26 21:43:36 +03:00
return 0 ;
2012-07-16 14:42:36 +04:00
}
static void smpboot_destroy_threads ( struct smp_hotplug_thread * ht )
{
unsigned int cpu ;
/* We need to destroy also the parked threads of offline cpus */
for_each_possible_cpu ( cpu ) {
struct task_struct * tsk = * per_cpu_ptr ( ht - > store , cpu ) ;
if ( tsk ) {
2023-09-08 02:40:48 +03:00
kthread_stop_put ( tsk ) ;
2012-07-16 14:42:36 +04:00
* per_cpu_ptr ( ht - > store , cpu ) = NULL ;
}
}
}
/**
2018-06-07 11:53:01 +03:00
* smpboot_register_percpu_thread - Register a per_cpu thread related
2015-09-05 01:45:06 +03:00
* to hotplug
2012-07-16 14:42:36 +04:00
* @ plug_thread : Hotplug thread descriptor
*
* Creates and starts the threads on all online cpus .
*/
2018-06-07 11:53:01 +03:00
int smpboot_register_percpu_thread ( struct smp_hotplug_thread * plug_thread )
2012-07-16 14:42:36 +04:00
{
unsigned int cpu ;
int ret = 0 ;
2021-08-03 17:16:16 +03:00
cpus_read_lock ( ) ;
2012-07-16 14:42:36 +04:00
mutex_lock ( & smpboot_threads_lock ) ;
for_each_online_cpu ( cpu ) {
ret = __smpboot_create_thread ( plug_thread , cpu ) ;
if ( ret ) {
smpboot_destroy_threads ( plug_thread ) ;
goto out ;
}
2018-06-07 11:53:01 +03:00
smpboot_unpark_thread ( plug_thread , cpu ) ;
2012-07-16 14:42:36 +04:00
}
list_add ( & plug_thread - > list , & hotplug_threads ) ;
out :
mutex_unlock ( & smpboot_threads_lock ) ;
2021-08-03 17:16:16 +03:00
cpus_read_unlock ( ) ;
2012-07-16 14:42:36 +04:00
return ret ;
}
2018-06-07 11:53:01 +03:00
EXPORT_SYMBOL_GPL ( smpboot_register_percpu_thread ) ;
2012-07-16 14:42:36 +04:00
/**
* smpboot_unregister_percpu_thread - Unregister a per_cpu thread related to hotplug
* @ plug_thread : Hotplug thread descriptor
*
* Stops all threads on all possible cpus .
*/
void smpboot_unregister_percpu_thread ( struct smp_hotplug_thread * plug_thread )
{
2021-08-03 17:16:16 +03:00
cpus_read_lock ( ) ;
2012-07-16 14:42:36 +04:00
mutex_lock ( & smpboot_threads_lock ) ;
list_del ( & plug_thread - > list ) ;
smpboot_destroy_threads ( plug_thread ) ;
mutex_unlock ( & smpboot_threads_lock ) ;
2021-08-03 17:16:16 +03:00
cpus_read_unlock ( ) ;
2012-07-16 14:42:36 +04:00
}
EXPORT_SYMBOL_GPL ( smpboot_unregister_percpu_thread ) ;