From patchwork Tue Jun 25 20:25:42 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Srivatsa S. Bhat" X-Patchwork-Id: 2781091 Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id CEBF79F3A0 for ; Tue, 25 Jun 2013 20:47:52 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CCDF7204E2 for ; Tue, 25 Jun 2013 20:47:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B7622204D1 for ; Tue, 25 Jun 2013 20:47:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752152Ab3FYU3V (ORCPT ); Tue, 25 Jun 2013 16:29:21 -0400 Received: from e23smtp08.au.ibm.com ([202.81.31.141]:36274 "EHLO e23smtp08.au.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752828Ab3FYU3T (ORCPT ); Tue, 25 Jun 2013 16:29:19 -0400 Received: from /spool/local by e23smtp08.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 26 Jun 2013 06:26:31 +1000 Received: from d23dlp01.au.ibm.com (202.81.31.203) by e23smtp08.au.ibm.com (202.81.31.205) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 26 Jun 2013 06:26:28 +1000 Received: from d23relay03.au.ibm.com (d23relay03.au.ibm.com [9.190.235.21]) by d23dlp01.au.ibm.com (Postfix) with ESMTP id 176332CE8052; Wed, 26 Jun 2013 06:29:12 +1000 (EST) Received: from d23av03.au.ibm.com (d23av03.au.ibm.com [9.190.234.97]) by d23relay03.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r5PKT21665405114; Wed, 26 Jun 2013 06:29:02 +1000 Received: from d23av03.au.ibm.com (loopback [127.0.0.1]) by d23av03.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id r5PKT9xR026370; Wed, 26 Jun 2013 06:29:11 +1000 Received: from srivatsabhat.in.ibm.com ([9.79.199.80]) by d23av03.au.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id r5PKStAo026230; Wed, 26 Jun 2013 06:29:02 +1000 From: "Srivatsa S. Bhat" Subject: [PATCH v2 01/45] CPU hotplug: Provide APIs to prevent CPU offline from atomic context To: tglx@linutronix.de, peterz@infradead.org, tj@kernel.org, oleg@redhat.com, paulmck@linux.vnet.ibm.com, rusty@rustcorp.com.au, mingo@kernel.org, akpm@linux-foundation.org, namhyung@kernel.org, walken@google.com, vincent.guittot@linaro.org, laijs@cn.fujitsu.com Cc: rostedt@goodmis.org, wangyun@linux.vnet.ibm.com, xiaoguangrong@linux.vnet.ibm.com, sbw@mit.edu, fweisbec@gmail.com, zhong@linux.vnet.ibm.com, nikunj@linux.vnet.ibm.com, srivatsa.bhat@linux.vnet.ibm.com, linux-pm@vger.kernel.org, linux-arch@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Thomas Gleixner , Andrew Morton , Tejun Heo , "Rafael J. Wysocki" , Yasuaki Ishimatsu , "Srivatsa S. Bhat" Date: Wed, 26 Jun 2013 01:55:42 +0530 Message-ID: <20130625202541.16593.17752.stgit@srivatsabhat.in.ibm.com> In-Reply-To: <20130625202452.16593.22810.stgit@srivatsabhat.in.ibm.com> References: <20130625202452.16593.22810.stgit@srivatsabhat.in.ibm.com> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 13062520-5140-0000-0000-0000036DD546 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org X-Spam-Status: No, score=-8.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The current CPU offline code uses stop_machine() internally. And disabling preemption prevents stop_machine() from taking effect, thus also preventing CPUs from going offline, as a side effect. There are places where this side-effect of preempt_disable() (or equivalent) is used to synchronize with CPU hotplug. Typically these are in atomic sections of code, where they can't make use of get/put_online_cpus(), because the latter set of APIs can sleep. Going forward, we want to get rid of stop_machine() from the CPU hotplug offline path. And then, with stop_machine() gone, disabling preemption will no longer prevent CPUs from going offline. So provide a set of APIs for such atomic hotplug readers, to prevent (any) CPUs from going offline. For now, they will default to preempt_disable() and preempt_enable() itself, but this will help us do the tree-wide conversion, as a preparatory step to remove stop_machine() from CPU hotplug. (Besides, it is good documentation as well, since it clearly marks places where we synchronize with CPU hotplug, instead of combining it subtly with disabling preemption). In future, when actually removing stop_machine(), we will alter the implementation of these APIs to a suitable synchronization scheme. Reviewed-by: Steven Rostedt Cc: Thomas Gleixner Cc: Andrew Morton Cc: Tejun Heo Cc: "Rafael J. Wysocki" Cc: Yasuaki Ishimatsu Signed-off-by: Srivatsa S. Bhat --- include/linux/cpu.h | 20 ++++++++++++++++++++ kernel/cpu.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 9f3c7e8..a57b25a 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -17,6 +17,8 @@ #include #include #include +#include +#include struct device; @@ -175,6 +177,8 @@ extern struct bus_type cpu_subsys; extern void get_online_cpus(void); extern void put_online_cpus(void); +extern unsigned int get_online_cpus_atomic(void); +extern void put_online_cpus_atomic(void); extern void cpu_hotplug_disable(void); extern void cpu_hotplug_enable(void); #define hotcpu_notifier(fn, pri) cpu_notifier(fn, pri) @@ -202,6 +206,22 @@ static inline void cpu_hotplug_driver_unlock(void) #define put_online_cpus() do { } while (0) #define cpu_hotplug_disable() do { } while (0) #define cpu_hotplug_enable() do { } while (0) + +static inline unsigned int get_online_cpus_atomic(void) +{ + /* + * Disable preemption to avoid getting complaints from the + * debug_smp_processor_id() code. + */ + preempt_disable(); + return smp_processor_id(); +} + +static inline void put_online_cpus_atomic(void) +{ + preempt_enable(); +} + #define hotcpu_notifier(fn, pri) do { (void)(fn); } while (0) /* These aren't inline functions due to a GCC bug. */ #define register_hotcpu_notifier(nb) ({ (void)(nb); 0; }) diff --git a/kernel/cpu.c b/kernel/cpu.c index 198a388..2d03398 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -154,6 +154,44 @@ void cpu_hotplug_enable(void) cpu_maps_update_done(); } +/* + * get_online_cpus_atomic - Prevent any CPU from going offline + * + * Atomic hotplug readers (tasks which wish to prevent CPUs from going + * offline during their critical section, but can't afford to sleep) + * can invoke this function to synchronize with CPU offline. This function + * can be called recursively, provided it is matched with an equal number + * of calls to put_online_cpus_atomic(). + * + * Note: This does NOT prevent CPUs from coming online! It only prevents + * CPUs from going offline. + * + * Lock ordering rule: Strictly speaking, there is no lock ordering + * requirement here, but it is advisable to keep the locking consistent. + * As a simple rule-of-thumb, use these functions in the outer-most blocks + * of your critical sections, outside of other locks. + * + * Returns the current CPU number, with preemption disabled. + */ +unsigned int get_online_cpus_atomic(void) +{ + /* + * The current CPU hotplug implementation uses stop_machine() in + * the CPU offline path. And disabling preemption prevents + * stop_machine() from taking effect. Thus, this prevents any CPU + * from going offline. + */ + preempt_disable(); + return smp_processor_id(); +} +EXPORT_SYMBOL_GPL(get_online_cpus_atomic); + +void put_online_cpus_atomic(void) +{ + preempt_enable(); +} +EXPORT_SYMBOL_GPL(put_online_cpus_atomic); + #else /* #if CONFIG_HOTPLUG_CPU */ static void cpu_hotplug_begin(void) {} static void cpu_hotplug_done(void) {}