Skip to content

Commit

Permalink
cpu/hotplug: Make wait for dead cpu completion based
Browse files Browse the repository at this point in the history
Kill the busy spinning on the control side and just wait for the hotplugged
cpu to tell that it reached the dead state.

Signed-off-by: Thomas Gleixner <[email protected]>
Cc: [email protected]
Cc: Rik van Riel <[email protected]>
Cc: Rafael Wysocki <[email protected]>
Cc: "Srivatsa S. Bhat" <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Arjan van de Ven <[email protected]>
Cc: Sebastian Siewior <[email protected]>
Cc: Rusty Russell <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Oleg Nesterov <[email protected]>
Cc: Tejun Heo <[email protected]>
Cc: Andrew Morton <[email protected]>
Cc: Paul McKenney <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Paul Turner <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Thomas Gleixner <[email protected]>
  • Loading branch information
KAGA-KOKO committed Mar 1, 2016
1 parent 8df3e07 commit e69aab1
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 10 deletions.
5 changes: 3 additions & 2 deletions include/linux/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,14 +276,15 @@ void arch_cpu_idle_enter(void);
void arch_cpu_idle_exit(void);
void arch_cpu_idle_dead(void);

DECLARE_PER_CPU(bool, cpu_dead_idle);

int cpu_report_state(int cpu);
int cpu_check_up_prepare(int cpu);
void cpu_set_state_online(int cpu);
#ifdef CONFIG_HOTPLUG_CPU
bool cpu_wait_death(unsigned int cpu, int seconds);
bool cpu_report_death(void);
void cpuhp_report_idle_dead(void);
#else
static inline void cpuhp_report_idle_dead(void) { }
#endif /* #ifdef CONFIG_HOTPLUG_CPU */

#endif /* _LINUX_CPU_H_ */
1 change: 1 addition & 0 deletions include/linux/cpuhotplug.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ enum cpuhp_state {
CPUHP_CREATE_THREADS,
CPUHP_NOTIFY_PREPARE,
CPUHP_BRINGUP_CPU,
CPUHP_AP_IDLE_DEAD,
CPUHP_AP_OFFLINE,
CPUHP_AP_NOTIFY_STARTING,
CPUHP_AP_ONLINE,
Expand Down
16 changes: 12 additions & 4 deletions kernel/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,7 @@ static int take_cpu_down(void *_param)

static int takedown_cpu(unsigned int cpu)
{
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
int err;

/*
Expand Down Expand Up @@ -733,10 +734,8 @@ static int takedown_cpu(unsigned int cpu)
*
* Wait for the stop thread to go away.
*/
while (!per_cpu(cpu_dead_idle, cpu))
cpu_relax();
smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */
per_cpu(cpu_dead_idle, cpu) = false;
wait_for_completion(&st->done);
BUG_ON(st->state != CPUHP_AP_IDLE_DEAD);

/* Interrupts are moved away from the dying cpu, reenable alloc/free */
irq_unlock_sparse();
Expand All @@ -756,6 +755,15 @@ static int notify_dead(unsigned int cpu)
return 0;
}

void cpuhp_report_idle_dead(void)
{
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);

BUG_ON(st->state != CPUHP_AP_OFFLINE);
st->state = CPUHP_AP_IDLE_DEAD;
complete(&st->done);
}

#else
#define notify_down_prepare NULL
#define takedown_cpu NULL
Expand Down
5 changes: 1 addition & 4 deletions kernel/sched/idle.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,6 @@ static void cpuidle_idle_call(void)
rcu_idle_exit();
}

DEFINE_PER_CPU(bool, cpu_dead_idle);

/*
* Generic idle loop implementation
*
Expand Down Expand Up @@ -224,8 +222,7 @@ static void cpu_idle_loop(void)
if (cpu_is_offline(smp_processor_id())) {
rcu_cpu_notify(NULL, CPU_DYING_IDLE,
(void *)(long)smp_processor_id());
smp_mb(); /* all activity before dead. */
this_cpu_write(cpu_dead_idle, true);
cpuhp_report_idle_dead();
arch_cpu_idle_dead();
}

Expand Down

0 comments on commit e69aab1

Please sign in to comment.