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
next prev 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).