aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2013-09-03 12:52:20 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2013-09-23 12:15:28 -0400
commit69c8d28c96445e28f081fcd987e34ea2afa65039 (patch)
tree8b7168675d2d11a4ddf82f74541d35fe94e6ba87 /kernel/rcutree.c
parent289828e62de0334a0d01c0f65df91cd47d3a9e05 (diff)
rcu: Micro-optimize rcu_cpu_has_callbacks()
The for_each_rcu_flavor() loop unconditionally scans all flavors, even when the first flavor might have some non-lazy callbacks. Once the loop has seen a non-lazy callback, further passes through the loop cannot change the state. This is not a huge problem, given that there can be at most three RCU flavors (RCU-bh, RCU-preempt, and RCU-sched), but this code is on the path to idle, so speeding it up even a small amount would have some benefit. This commit therefore does two things: 1. Rearranges the order of the list of RCU flavors in order to place the most active flavor first in the list. The most active RCU flavor is RCU-preempt, or, if there is no RCU-preempt, RCU-sched. 2. Reworks the for_each_rcu_flavor() to exit early when the first non-lazy callback is seen, or, in the case where the caller does not care about non-lazy callbacks (RCU_FAST_NO_HZ=n), when the first callback is seen. Reported-by: Chen Gang <gang.chen@asianux.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r--kernel/rcutree.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index e6f2e8f14140..49464aded7f7 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -2727,10 +2727,13 @@ static int rcu_cpu_has_callbacks(int cpu, bool *all_lazy)
2727 2727
2728 for_each_rcu_flavor(rsp) { 2728 for_each_rcu_flavor(rsp) {
2729 rdp = per_cpu_ptr(rsp->rda, cpu); 2729 rdp = per_cpu_ptr(rsp->rda, cpu);
2730 if (rdp->qlen != rdp->qlen_lazy) 2730 if (!rdp->nxtlist)
2731 continue;
2732 hc = true;
2733 if (rdp->qlen != rdp->qlen_lazy || !all_lazy) {
2731 al = false; 2734 al = false;
2732 if (rdp->nxtlist) 2735 break;
2733 hc = true; 2736 }
2734 } 2737 }
2735 if (all_lazy) 2738 if (all_lazy)
2736 *all_lazy = al; 2739 *all_lazy = al;
@@ -3297,8 +3300,8 @@ void __init rcu_init(void)
3297 3300
3298 rcu_bootup_announce(); 3301 rcu_bootup_announce();
3299 rcu_init_geometry(); 3302 rcu_init_geometry();
3300 rcu_init_one(&rcu_sched_state, &rcu_sched_data);
3301 rcu_init_one(&rcu_bh_state, &rcu_bh_data); 3303 rcu_init_one(&rcu_bh_state, &rcu_bh_data);
3304 rcu_init_one(&rcu_sched_state, &rcu_sched_data);
3302 __rcu_init_preempt(); 3305 __rcu_init_preempt();
3303 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); 3306 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
3304 3307