aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2013-11-05 16:03:17 -0500
committerSteven Rostedt <rostedt@goodmis.org>2013-11-05 16:03:17 -0500
commit44847da1b921f35b348ecd46df93abfbcd547355 (patch)
tree0dcc929a02b98dcf0927b9ad70083087c6d0e4ae /kernel
parentab4ead02ec235d706d0611d8741964628291237e (diff)
parent5c173eb8bcb9c1aa888bd6d14a4cb746f3dd2420 (diff)
Merge branch 'idle.2013.09.25a' of git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu into HEAD
Need to use Paul McKenney's "rcu_is_watching()" changes to fix a perf/ftrace bug.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/lockdep.c4
-rw-r--r--kernel/rcupdate.c2
-rw-r--r--kernel/rcutiny.c10
-rw-r--r--kernel/rcutree.c23
-rw-r--r--kernel/rcutree.h2
-rw-r--r--kernel/rcutree_plugin.h24
6 files changed, 41 insertions, 24 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index e16c45b9ee77..4e8e14c34e42 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -4224,7 +4224,7 @@ void lockdep_rcu_suspicious(const char *file, const int line, const char *s)
4224 printk("\n%srcu_scheduler_active = %d, debug_locks = %d\n", 4224 printk("\n%srcu_scheduler_active = %d, debug_locks = %d\n",
4225 !rcu_lockdep_current_cpu_online() 4225 !rcu_lockdep_current_cpu_online()
4226 ? "RCU used illegally from offline CPU!\n" 4226 ? "RCU used illegally from offline CPU!\n"
4227 : rcu_is_cpu_idle() 4227 : !rcu_is_watching()
4228 ? "RCU used illegally from idle CPU!\n" 4228 ? "RCU used illegally from idle CPU!\n"
4229 : "", 4229 : "",
4230 rcu_scheduler_active, debug_locks); 4230 rcu_scheduler_active, debug_locks);
@@ -4247,7 +4247,7 @@ void lockdep_rcu_suspicious(const char *file, const int line, const char *s)
4247 * So complain bitterly if someone does call rcu_read_lock(), 4247 * So complain bitterly if someone does call rcu_read_lock(),
4248 * rcu_read_lock_bh() and so on from extended quiescent states. 4248 * rcu_read_lock_bh() and so on from extended quiescent states.
4249 */ 4249 */
4250 if (rcu_is_cpu_idle()) 4250 if (!rcu_is_watching())
4251 printk("RCU used illegally from extended quiescent state!\n"); 4251 printk("RCU used illegally from extended quiescent state!\n");
4252 4252
4253 lockdep_print_held_locks(curr); 4253 lockdep_print_held_locks(curr);
diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c
index b02a339836b4..3b3c0464d1eb 100644
--- a/kernel/rcupdate.c
+++ b/kernel/rcupdate.c
@@ -148,7 +148,7 @@ int rcu_read_lock_bh_held(void)
148{ 148{
149 if (!debug_lockdep_rcu_enabled()) 149 if (!debug_lockdep_rcu_enabled())
150 return 1; 150 return 1;
151 if (rcu_is_cpu_idle()) 151 if (!rcu_is_watching())
152 return 0; 152 return 0;
153 if (!rcu_lockdep_current_cpu_online()) 153 if (!rcu_lockdep_current_cpu_online())
154 return 0; 154 return 0;
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c
index 9ed6075dc562..0fa061dfa55d 100644
--- a/kernel/rcutiny.c
+++ b/kernel/rcutiny.c
@@ -174,18 +174,18 @@ void rcu_irq_enter(void)
174} 174}
175EXPORT_SYMBOL_GPL(rcu_irq_enter); 175EXPORT_SYMBOL_GPL(rcu_irq_enter);
176 176
177#ifdef CONFIG_DEBUG_LOCK_ALLOC 177#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE)
178 178
179/* 179/*
180 * Test whether RCU thinks that the current CPU is idle. 180 * Test whether RCU thinks that the current CPU is idle.
181 */ 181 */
182int rcu_is_cpu_idle(void) 182bool __rcu_is_watching(void)
183{ 183{
184 return !rcu_dynticks_nesting; 184 return rcu_dynticks_nesting;
185} 185}
186EXPORT_SYMBOL(rcu_is_cpu_idle); 186EXPORT_SYMBOL(__rcu_is_watching);
187 187
188#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ 188#endif /* defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */
189 189
190/* 190/*
191 * Test whether the current CPU was interrupted from idle. Nested 191 * Test whether the current CPU was interrupted from idle. Nested
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 32618b3fe4e6..981d0c15a389 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -655,21 +655,34 @@ void rcu_nmi_exit(void)
655} 655}
656 656
657/** 657/**
658 * rcu_is_cpu_idle - see if RCU thinks that the current CPU is idle 658 * __rcu_is_watching - are RCU read-side critical sections safe?
659 *
660 * Return true if RCU is watching the running CPU, which means that
661 * this CPU can safely enter RCU read-side critical sections. Unlike
662 * rcu_is_watching(), the caller of __rcu_is_watching() must have at
663 * least disabled preemption.
664 */
665bool __rcu_is_watching(void)
666{
667 return atomic_read(this_cpu_ptr(&rcu_dynticks.dynticks)) & 0x1;
668}
669
670/**
671 * rcu_is_watching - see if RCU thinks that the current CPU is idle
659 * 672 *
660 * If the current CPU is in its idle loop and is neither in an interrupt 673 * If the current CPU is in its idle loop and is neither in an interrupt
661 * or NMI handler, return true. 674 * or NMI handler, return true.
662 */ 675 */
663int rcu_is_cpu_idle(void) 676bool rcu_is_watching(void)
664{ 677{
665 int ret; 678 int ret;
666 679
667 preempt_disable(); 680 preempt_disable();
668 ret = (atomic_read(&__get_cpu_var(rcu_dynticks).dynticks) & 0x1) == 0; 681 ret = __rcu_is_watching();
669 preempt_enable(); 682 preempt_enable();
670 return ret; 683 return ret;
671} 684}
672EXPORT_SYMBOL(rcu_is_cpu_idle); 685EXPORT_SYMBOL_GPL(rcu_is_watching);
673 686
674#if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU) 687#if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU)
675 688
@@ -2255,7 +2268,7 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
2255 * If called from an extended quiescent state, invoke the RCU 2268 * If called from an extended quiescent state, invoke the RCU
2256 * core in order to force a re-evaluation of RCU's idleness. 2269 * core in order to force a re-evaluation of RCU's idleness.
2257 */ 2270 */
2258 if (rcu_is_cpu_idle() && cpu_online(smp_processor_id())) 2271 if (!rcu_is_watching() && cpu_online(smp_processor_id()))
2259 invoke_rcu_core(); 2272 invoke_rcu_core();
2260 2273
2261 /* If interrupts were disabled or CPU offline, don't invoke RCU core. */ 2274 /* If interrupts were disabled or CPU offline, don't invoke RCU core. */
diff --git a/kernel/rcutree.h b/kernel/rcutree.h
index 5f97eab602cd..52be957c9fe2 100644
--- a/kernel/rcutree.h
+++ b/kernel/rcutree.h
@@ -104,6 +104,8 @@ struct rcu_dynticks {
104 /* idle-period nonlazy_posted snapshot. */ 104 /* idle-period nonlazy_posted snapshot. */
105 unsigned long last_accelerate; 105 unsigned long last_accelerate;
106 /* Last jiffy CBs were accelerated. */ 106 /* Last jiffy CBs were accelerated. */
107 unsigned long last_advance_all;
108 /* Last jiffy CBs were all advanced. */
107 int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */ 109 int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */
108#endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */ 110#endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
109}; 111};
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 130c97b027f2..2c15d7c10684 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -1630,17 +1630,23 @@ module_param(rcu_idle_lazy_gp_delay, int, 0644);
1630extern int tick_nohz_enabled; 1630extern int tick_nohz_enabled;
1631 1631
1632/* 1632/*
1633 * Try to advance callbacks for all flavors of RCU on the current CPU. 1633 * Try to advance callbacks for all flavors of RCU on the current CPU, but
1634 * Afterwards, if there are any callbacks ready for immediate invocation, 1634 * only if it has been awhile since the last time we did so. Afterwards,
1635 * return true. 1635 * if there are any callbacks ready for immediate invocation, return true.
1636 */ 1636 */
1637static bool rcu_try_advance_all_cbs(void) 1637static bool rcu_try_advance_all_cbs(void)
1638{ 1638{
1639 bool cbs_ready = false; 1639 bool cbs_ready = false;
1640 struct rcu_data *rdp; 1640 struct rcu_data *rdp;
1641 struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
1641 struct rcu_node *rnp; 1642 struct rcu_node *rnp;
1642 struct rcu_state *rsp; 1643 struct rcu_state *rsp;
1643 1644
1645 /* Exit early if we advanced recently. */
1646 if (jiffies == rdtp->last_advance_all)
1647 return 0;
1648 rdtp->last_advance_all = jiffies;
1649
1644 for_each_rcu_flavor(rsp) { 1650 for_each_rcu_flavor(rsp) {
1645 rdp = this_cpu_ptr(rsp->rda); 1651 rdp = this_cpu_ptr(rsp->rda);
1646 rnp = rdp->mynode; 1652 rnp = rdp->mynode;
@@ -1739,6 +1745,8 @@ static void rcu_prepare_for_idle(int cpu)
1739 */ 1745 */
1740 if (rdtp->all_lazy && 1746 if (rdtp->all_lazy &&
1741 rdtp->nonlazy_posted != rdtp->nonlazy_posted_snap) { 1747 rdtp->nonlazy_posted != rdtp->nonlazy_posted_snap) {
1748 rdtp->all_lazy = false;
1749 rdtp->nonlazy_posted_snap = rdtp->nonlazy_posted;
1742 invoke_rcu_core(); 1750 invoke_rcu_core();
1743 return; 1751 return;
1744 } 1752 }
@@ -1768,17 +1776,11 @@ static void rcu_prepare_for_idle(int cpu)
1768 */ 1776 */
1769static void rcu_cleanup_after_idle(int cpu) 1777static void rcu_cleanup_after_idle(int cpu)
1770{ 1778{
1771 struct rcu_data *rdp;
1772 struct rcu_state *rsp;
1773 1779
1774 if (rcu_is_nocb_cpu(cpu)) 1780 if (rcu_is_nocb_cpu(cpu))
1775 return; 1781 return;
1776 rcu_try_advance_all_cbs(); 1782 if (rcu_try_advance_all_cbs())
1777 for_each_rcu_flavor(rsp) { 1783 invoke_rcu_core();
1778 rdp = per_cpu_ptr(rsp->rda, cpu);
1779 if (cpu_has_callbacks_ready_to_invoke(rdp))
1780 invoke_rcu_core();
1781 }
1782} 1784}
1783 1785
1784/* 1786/*