linux-arch.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Ingo Molnar <mingo@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Peter Anvin <hpa@zytor.com>, Oleg Nesterov <oleg@redhat.com>,
	linux-arch@vger.kernel.org, Tejun Heo <tj@kernel.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Rusty Russell <rusty@rustcorp.com.au>,
	Paul McKenney <paulmck@linux.vnet.ibm.com>,
	Rafael Wysocki <rafael.j.wysocki@intel.com>,
	Arjan van de Ven <arjan@linux.intel.com>,
	Rik van Riel <riel@redhat.com>,
	"Srivatsa S. Bhat" <srivatsa@mit.edu>,
	Sebastian Siewior <bigeasy@linutronix.de>,
	Paul Turner <pjt@google.com>
Subject: [patch 15/20] cpu/hotplug: Create hotplug threads
Date: Fri, 26 Feb 2016 18:43:38 -0000	[thread overview]
Message-ID: <20160226182341.454541272@linutronix.de> (raw)
In-Reply-To: 20160226164321.657646833@linutronix.de

[-- Attachment #1: hotplug--Create-hotplug-threads.patch --]
[-- Type: text/plain, Size: 6098 bytes --]

In order to let the hotplugged cpu take care of the setup/teardown, we need a
seperate hotplug thread.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/cpu.c     |  145 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 kernel/smp.c     |    1 
 kernel/smpboot.h |    2 
 3 files changed, 147 insertions(+), 1 deletion(-)

Index: b/kernel/cpu.c
===================================================================
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -22,6 +22,7 @@
 #include <linux/lockdep.h>
 #include <linux/tick.h>
 #include <linux/irq.h>
+#include <linux/smpboot.h>
 
 #include <trace/events/power.h>
 #define CREATE_TRACE_POINTS
@@ -33,10 +34,24 @@
  * cpuhp_cpu_state - Per cpu hotplug state storage
  * @state:	The current cpu state
  * @target:	The target state
+ * @thread:	Pointer to the hotplug thread
+ * @should_run:	Thread should execute
+ * @cb_stat:	The state for a single callback (install/uninstall)
+ * @cb:		Single callback function (install/uninstall)
+ * @result:	Result of the operation
+ * @done:	Signal completion to the issuer of the task
  */
 struct cpuhp_cpu_state {
 	enum cpuhp_state	state;
 	enum cpuhp_state	target;
+#ifdef CONFIG_SMP
+	struct task_struct	*thread;
+	bool			should_run;
+	enum cpuhp_state	cb_state;
+	int			(*cb)(unsigned int cpu);
+	int			result;
+	struct completion	done;
+#endif
 };
 
 static DEFINE_PER_CPU(struct cpuhp_cpu_state, cpuhp_state);
@@ -394,6 +409,134 @@ static int cpuhp_up_callbacks(unsigned i
 	return ret;
 }
 
+/*
+ * The cpu hotplug threads manage the bringup and teardown of the cpus
+ */
+static void cpuhp_create(unsigned int cpu)
+{
+	struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+
+	init_completion(&st->done);
+}
+
+static int cpuhp_should_run(unsigned int cpu)
+{
+	struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
+
+	return st->should_run;
+}
+
+/* Execute the teardown callbacks. Used to be CPU_DOWN_PREPARE */
+static int cpuhp_ap_offline(unsigned int cpu, struct cpuhp_cpu_state *st)
+{
+	enum cpuhp_state target = max((int)st->target, CPUHP_AP_ONLINE);
+
+	return cpuhp_down_callbacks(cpu, st, cpuhp_ap_states, target);
+}
+
+/* Execute the online startup callbacks. Used to be CPU_ONLINE */
+static int cpuhp_ap_online(unsigned int cpu, struct cpuhp_cpu_state *st)
+{
+	return cpuhp_up_callbacks(cpu, st, cpuhp_ap_states, st->target);
+}
+
+/*
+ * Execute teardown/startup callbacks on the plugged cpu. Also used to invoke
+ * callbacks when a state gets [un]installed at runtime.
+ */
+static void cpuhp_thread_fun(unsigned int cpu)
+{
+	struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
+	int ret = 0;
+
+	/*
+	 * Paired with the mb() in cpuhp_kick_ap_work and
+	 * cpuhp_invoke_ap_callback, so the work set is consistent visible.
+	 */
+	smp_mb();
+	if (!st->should_run)
+		return;
+
+	st->should_run = false;
+
+	/* Single callback invocation for [un]install ? */
+	if (st->cb) {
+		if (st->cb_state < CPUHP_AP_ONLINE) {
+			local_irq_disable();
+			ret = cpuhp_invoke_callback(cpu, st->cb_state, st->cb);
+			local_irq_enable();
+		} else {
+			ret = cpuhp_invoke_callback(cpu, st->cb_state, st->cb);
+		}
+	} else {
+		/* Regular hotplug work */
+		if (st->state < st->target)
+			ret = cpuhp_ap_online(cpu, st);
+		else if (st->state > st->target)
+			ret = cpuhp_ap_offline(cpu, st);
+	}
+	st->result = ret;
+	complete(&st->done);
+}
+
+/* Invoke a single callback on a remote cpu */
+static int cpuhp_invoke_ap_callback(int cpu, enum cpuhp_state state,
+				    int (*cb)(unsigned int))
+{
+	struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+
+	if (!cpu_online(cpu))
+		return 0;
+
+	st->cb_state = state;
+	st->cb = cb;
+	/*
+	 * Make sure the above stores are visible before should_run becomes
+	 * true. Paired with the mb() above in cpuhp_thread_fun()
+	 */
+	smp_mb();
+	st->should_run = true;
+	wake_up_process(st->thread);
+	wait_for_completion(&st->done);
+	return st->result;
+}
+
+/* Regular hotplug invocation of the AP hotplug thread */
+static int cpuhp_kick_ap_work(unsigned int cpu)
+{
+	struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+	enum cpuhp_state state = st->state;
+
+	trace_cpuhp_enter(cpu, st->target, state, cpuhp_kick_ap_work);
+	st->result = 0;
+	st->cb = NULL;
+	/*
+	 * Make sure the above stores are visible before should_run becomes
+	 * true. Paired with the mb() above in cpuhp_thread_fun()
+	 */
+	smp_mb();
+	st->should_run = true;
+	wake_up_process(st->thread);
+	wait_for_completion(&st->done);
+	trace_cpuhp_exit(cpu, st->state, state, st->result);
+	return st->result;
+}
+
+static struct smp_hotplug_thread cpuhp_threads = {
+	.store			= &cpuhp_state.thread,
+	.create			= &cpuhp_create,
+	.thread_should_run	= cpuhp_should_run,
+	.thread_fn		= cpuhp_thread_fun,
+	.thread_comm		= "cpuhp/%u",
+	.selfparking		= true,
+};
+
+void __init cpuhp_threads_init(void)
+{
+	BUG_ON(smpboot_register_percpu_thread(&cpuhp_threads));
+	kthread_unpark(this_cpu_read(cpuhp_state.thread));
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 EXPORT_SYMBOL(register_cpu_notifier);
 EXPORT_SYMBOL(__register_cpu_notifier);
@@ -997,7 +1140,7 @@ static int cpuhp_cb_check(enum cpuhp_sta
 
 static bool cpuhp_is_ap_state(enum cpuhp_state state)
 {
-	return (state > CPUHP_AP_OFFLINE && state < CPUHP_AP_ONLINE);
+	return (state >= CPUHP_AP_OFFLINE && state <= CPUHP_AP_ONLINE);
 }
 
 static struct cpuhp_step *cpuhp_get_step(enum cpuhp_state state)
Index: b/kernel/smp.c
===================================================================
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -569,6 +569,7 @@ void __init smp_init(void)
 	unsigned int cpu;
 
 	idle_threads_init();
+	cpuhp_threads_init();
 
 	/* FIXME: This should be done in userspace --RR */
 	for_each_present_cpu(cpu) {
Index: b/kernel/smpboot.h
===================================================================
--- a/kernel/smpboot.h
+++ b/kernel/smpboot.h
@@ -17,4 +17,6 @@ int smpboot_create_threads(unsigned int
 int smpboot_park_threads(unsigned int cpu);
 int smpboot_unpark_threads(unsigned int cpu);
 
+void __init cpuhp_threads_init(void);
+
 #endif

  parent reply	other threads:[~2016-02-26 18:43 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-26 18:43 [patch 00/20] cpu/hotplug: Core infrastructure for cpu hotplug rework Thomas Gleixner
2016-02-26 18:43 ` Thomas Gleixner
2016-02-26 18:43 ` [patch 01/20] idle: Move x86ism out of generic code Thomas Gleixner
2016-02-27 20:29   ` Brian Gerst
2016-02-29 19:35     ` Thomas Gleixner
2016-02-29 19:48       ` Will Deacon
2016-02-29 20:06         ` Thomas Gleixner
2016-02-26 18:43 ` [patch 02/20] cpu/hotplug: Restructure FROZEN state handling Thomas Gleixner
2016-02-26 18:43 ` [patch 03/20] cpu/hotplug: Restructure cpu_up code Thomas Gleixner
2016-02-26 18:43 ` [patch 04/20] cpu/hotplug: Split out cpu down functions Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 18:43 ` [patch 05/20] cpu/hotplug: Add tracepoints Thomas Gleixner
2016-02-26 18:43 ` [patch 06/20] cpu/hotplug: Convert to a state machine for the control processor Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 18:43 ` [patch 07/20] cpu/hotplug: Convert the hotplugged cpu work to a state machine Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 18:43 ` [patch 08/20] cpu/hotplug: Hand in target state to _cpu_up/down Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 18:43 ` [patch 09/20] cpu/hotplug: Add sysfs state interface Thomas Gleixner
2016-02-26 18:43 ` [patch 10/20] cpu/hotplug: Make target state writeable Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 23:46   ` Rafael J. Wysocki
2016-02-27  7:39     ` Thomas Gleixner
2016-02-27 14:43       ` Rafael J. Wysocki
2016-02-28 14:49         ` Thomas Gleixner
2016-02-28 14:49           ` Thomas Gleixner
2016-02-29 15:49           ` Thomas Gleixner
2016-03-01  1:53             ` Rafael J. Wysocki
2016-02-26 18:43 ` [patch 11/20] cpu/hotplug: Implement setup/removal interface Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 18:43 ` [patch 12/20] cpu/hotplug: Move scheduler cpu_online notifier to hotplug core Thomas Gleixner
2016-02-26 18:43 ` [patch 13/20] cpu/hotplug: Unpark smpboot threads from the state machine Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 18:43 ` [patch 14/20] cpu/hotplug: Split out the state walk into functions Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 18:43 ` Thomas Gleixner [this message]
2016-02-26 18:43   ` [patch 15/20] cpu/hotplug: Create hotplug threads Thomas Gleixner
2016-02-26 18:43 ` [patch 16/20] cpu/hotplug: Move online calls to hotplugged cpu Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 18:43 ` [patch 17/20] arch/hotplug: Call into idle with a proper state Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 18:43 ` [patch 18/20] cpu/hotplug: Let upcoming cpu bring itself fully up Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-03-02 17:28   ` Richard Cochran
2016-02-26 18:43 ` [patch 19/20] cpu/hotplug: Make wait for dead cpu completion based Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-26 18:43 ` [patch 20/20] rcu: Make CPU_DYING_IDLE an explicit call Thomas Gleixner
2016-02-26 18:43   ` Thomas Gleixner
2016-02-27  2:14   ` Paul E. McKenney
2016-02-27  2:23     ` Paul E. McKenney
2016-02-27  7:47       ` Thomas Gleixner
2016-02-27 11:05         ` Paul E. McKenney
2016-02-27 11:30           ` Thomas Gleixner
2016-02-27 11:30             ` Thomas Gleixner
2016-02-27 16:33             ` Paul E. McKenney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160226182341.454541272@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=akpm@linux-foundation.org \
    --cc=arjan@linux.intel.com \
    --cc=bigeasy@linutronix.de \
    --cc=hpa@zytor.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=oleg@redhat.com \
    --cc=paulmck@linux.vnet.ibm.com \
    --cc=peterz@infradead.org \
    --cc=pjt@google.com \
    --cc=rafael.j.wysocki@intel.com \
    --cc=riel@redhat.com \
    --cc=rostedt@goodmis.org \
    --cc=rusty@rustcorp.com.au \
    --cc=srivatsa@mit.edu \
    --cc=tj@kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).