diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2013-11-05 16:03:17 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2013-11-05 16:03:17 -0500 |
commit | 44847da1b921f35b348ecd46df93abfbcd547355 (patch) | |
tree | 0dcc929a02b98dcf0927b9ad70083087c6d0e4ae /kernel | |
parent | ab4ead02ec235d706d0611d8741964628291237e (diff) | |
parent | 5c173eb8bcb9c1aa888bd6d14a4cb746f3dd2420 (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.c | 4 | ||||
-rw-r--r-- | kernel/rcupdate.c | 2 | ||||
-rw-r--r-- | kernel/rcutiny.c | 10 | ||||
-rw-r--r-- | kernel/rcutree.c | 23 | ||||
-rw-r--r-- | kernel/rcutree.h | 2 | ||||
-rw-r--r-- | kernel/rcutree_plugin.h | 24 |
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 | } |
175 | EXPORT_SYMBOL_GPL(rcu_irq_enter); | 175 | EXPORT_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 | */ |
182 | int rcu_is_cpu_idle(void) | 182 | bool __rcu_is_watching(void) |
183 | { | 183 | { |
184 | return !rcu_dynticks_nesting; | 184 | return rcu_dynticks_nesting; |
185 | } | 185 | } |
186 | EXPORT_SYMBOL(rcu_is_cpu_idle); | 186 | EXPORT_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 | */ | ||
665 | bool __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 | */ |
663 | int rcu_is_cpu_idle(void) | 676 | bool 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 | } |
672 | EXPORT_SYMBOL(rcu_is_cpu_idle); | 685 | EXPORT_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); | |||
1630 | extern int tick_nohz_enabled; | 1630 | extern 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 | */ |
1637 | static bool rcu_try_advance_all_cbs(void) | 1637 | static 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 | */ |
1769 | static void rcu_cleanup_after_idle(int cpu) | 1777 | static 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 | /* |