From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S965222Ab2CUOB2 (ORCPT ); Wed, 21 Mar 2012 10:01:28 -0400 Received: from mail-wg0-f44.google.com ([74.125.82.44]:47416 "EHLO mail-wg0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1031121Ab2CUOAX (ORCPT ); Wed, 21 Mar 2012 10:00:23 -0400 From: Frederic Weisbecker To: LKML , linaro-sched-sig@lists.linaro.org Cc: Frederic Weisbecker , Alessio Igor Bogani , Andrew Morton , Avi Kivity , Chris Metcalf , Christoph Lameter , Daniel Lezcano , Geoff Levand , Gilad Ben Yossef , Ingo Molnar , Max Krasnyansky , "Paul E. McKenney" , Peter Zijlstra , Stephen Hemminger , Steven Rostedt , Sven-Thorsten Dietrich , Thomas Gleixner , Zen Lin Subject: [PATCH 29/32] rcu: New rcu_user_enter_irq() and rcu_user_exit_irq() APIs Date: Wed, 21 Mar 2012 14:58:35 +0100 Message-Id: <1332338318-5958-31-git-send-email-fweisbec@gmail.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1332338318-5958-1-git-send-email-fweisbec@gmail.com> References: <1332338318-5958-1-git-send-email-fweisbec@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org A CPU running in adaptive tickless mode wants to enter into RCU extended quiescent state while running in userspace. This way we can shut down the tick that is usually needed on each CPU for the needs of RCU. Typically, RCU enters the extended quiescent state when we resume to userspace through a syscall or exception exit, this is done using rcu_user_enter(). Then RCU exit this state by calling rcu_user_exit() from syscall or exception entry. However there are two other points where we may want to enter or exit this state. Some remote CPU may require a tickless CPU to restart its tick for any reason and send it an IPI for this purpose. As we restart the tick, we don't want to resume from the IPI in RCU extended quiescent state anymore. Similarly we may stop the tick from an interrupt in userspace and we need to be able to enter RCU extended quiescent state when we resume from this interrupt to userspace. To these ends, we provide two new APIs: - rcu_user_enter_irq(). This must be called from a non-nesting interrupt betwenn rcu_irq_enter() and rcu_irq_exit(). After the irq calls rcu_irq_exit(), we'll run into RCU extended quiescent state. - rcu_user_exit_irq(). This must be called from a non-nesting interrupt, interrupting an RCU extended quiescent state, and between rcu_irq_enter() and rcu_irq_exit(). After the irq calls rcu_irq_exit(), we'll prevent from resuming the RCU extended quiescent. Signed-off-by: Frederic Weisbecker Cc: Alessio Igor Bogani Cc: Andrew Morton Cc: Avi Kivity Cc: Chris Metcalf Cc: Christoph Lameter Cc: Daniel Lezcano Cc: Geoff Levand Cc: Gilad Ben Yossef Cc: Ingo Molnar Cc: Max Krasnyansky Cc: Paul E. McKenney Cc: Peter Zijlstra Cc: Stephen Hemminger Cc: Steven Rostedt Cc: Sven-Thorsten Dietrich Cc: Thomas Gleixner Cc: Zen Lin --- include/linux/rcupdate.h | 2 ++ kernel/rcutree.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 0 deletions(-) diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 6539290..3cf1d51 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -194,6 +194,8 @@ extern void rcu_irq_exit(void); #ifdef CONFIG_CPUSETS_NO_HZ void rcu_user_enter(void); void rcu_user_exit(void); +void rcu_user_enter_irq(void); +void rcu_user_exit_irq(void); #endif /* diff --git a/kernel/rcutree.c b/kernel/rcutree.c index cba1332..2adc5a0 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -429,6 +429,18 @@ void rcu_user_enter(void) __rcu_idle_enter(); } +void rcu_user_enter_irq(void) +{ + unsigned long flags; + struct rcu_dynticks *rdtp; + + local_irq_save(flags); + rdtp = &__get_cpu_var(rcu_dynticks); + WARN_ON_ONCE(rdtp->dynticks_nesting == 1); + rdtp->dynticks_nesting = 1; + local_irq_restore(flags); +} + /** * rcu_irq_exit - inform RCU that current CPU is exiting irq towards idle * @@ -543,6 +555,18 @@ void rcu_user_exit(void) local_irq_restore(flags); } +void rcu_user_exit_irq(void) +{ + unsigned long flags; + struct rcu_dynticks *rdtp; + + local_irq_save(flags); + rdtp = &__get_cpu_var(rcu_dynticks); + WARN_ON_ONCE(rdtp->dynticks_nesting == 0); + rdtp->dynticks_nesting = (LLONG_MAX / 2) + 1; + local_irq_restore(flags); +} + /** * rcu_irq_enter - inform RCU that current CPU is entering irq away from idle * -- 1.7.5.4