aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2014-09-03 15:25:56 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2014-10-28 16:49:30 -0400
commite0775cefb5ede661dbdc0611d7bf3fcd4640005c (patch)
tree58bf71c00bef3462c92649ef80b393c44dd412f5
parent61cfd0970ea27764434fba5c41bdaefb26c44183 (diff)
rcu: Avoid IPIing idle CPUs from synchronize_sched_expedited()
Currently, synchronize_sched_expedited() sends IPIs to all online CPUs, even those that are idle or executing in nohz_full= userspace. Because idle CPUs and nohz_full= userspace CPUs are in extended quiescent states, there is no need to IPI them in the first place. This commit therefore avoids IPIing CPUs that are already in extended quiescent states. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r--kernel/rcu/tree.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 7f73c5edf8cf..9e3c20f117cd 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -2950,6 +2950,9 @@ static int synchronize_sched_expedited_cpu_stop(void *data)
2950 */ 2950 */
2951void synchronize_sched_expedited(void) 2951void synchronize_sched_expedited(void)
2952{ 2952{
2953 cpumask_var_t cm;
2954 bool cma = false;
2955 int cpu;
2953 long firstsnap, s, snap; 2956 long firstsnap, s, snap;
2954 int trycount = 0; 2957 int trycount = 0;
2955 struct rcu_state *rsp = &rcu_sched_state; 2958 struct rcu_state *rsp = &rcu_sched_state;
@@ -2984,11 +2987,26 @@ void synchronize_sched_expedited(void)
2984 } 2987 }
2985 WARN_ON_ONCE(cpu_is_offline(raw_smp_processor_id())); 2988 WARN_ON_ONCE(cpu_is_offline(raw_smp_processor_id()));
2986 2989
2990 /* Offline CPUs, idle CPUs, and any CPU we run on are quiescent. */
2991 cma = zalloc_cpumask_var(&cm, GFP_KERNEL);
2992 if (cma) {
2993 cpumask_copy(cm, cpu_online_mask);
2994 cpumask_clear_cpu(raw_smp_processor_id(), cm);
2995 for_each_cpu(cpu, cm) {
2996 struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
2997
2998 if (!(atomic_add_return(0, &rdtp->dynticks) & 0x1))
2999 cpumask_clear_cpu(cpu, cm);
3000 }
3001 if (cpumask_weight(cm) == 0)
3002 goto all_cpus_idle;
3003 }
3004
2987 /* 3005 /*
2988 * Each pass through the following loop attempts to force a 3006 * Each pass through the following loop attempts to force a
2989 * context switch on each CPU. 3007 * context switch on each CPU.
2990 */ 3008 */
2991 while (try_stop_cpus(cpu_online_mask, 3009 while (try_stop_cpus(cma ? cm : cpu_online_mask,
2992 synchronize_sched_expedited_cpu_stop, 3010 synchronize_sched_expedited_cpu_stop,
2993 NULL) == -EAGAIN) { 3011 NULL) == -EAGAIN) {
2994 put_online_cpus(); 3012 put_online_cpus();
@@ -3000,6 +3018,7 @@ void synchronize_sched_expedited(void)
3000 /* ensure test happens before caller kfree */ 3018 /* ensure test happens before caller kfree */
3001 smp_mb__before_atomic(); /* ^^^ */ 3019 smp_mb__before_atomic(); /* ^^^ */
3002 atomic_long_inc(&rsp->expedited_workdone1); 3020 atomic_long_inc(&rsp->expedited_workdone1);
3021 free_cpumask_var(cm);
3003 return; 3022 return;
3004 } 3023 }
3005 3024
@@ -3009,6 +3028,7 @@ void synchronize_sched_expedited(void)
3009 } else { 3028 } else {
3010 wait_rcu_gp(call_rcu_sched); 3029 wait_rcu_gp(call_rcu_sched);
3011 atomic_long_inc(&rsp->expedited_normal); 3030 atomic_long_inc(&rsp->expedited_normal);
3031 free_cpumask_var(cm);
3012 return; 3032 return;
3013 } 3033 }
3014 3034
@@ -3018,6 +3038,7 @@ void synchronize_sched_expedited(void)
3018 /* ensure test happens before caller kfree */ 3038 /* ensure test happens before caller kfree */
3019 smp_mb__before_atomic(); /* ^^^ */ 3039 smp_mb__before_atomic(); /* ^^^ */
3020 atomic_long_inc(&rsp->expedited_workdone2); 3040 atomic_long_inc(&rsp->expedited_workdone2);
3041 free_cpumask_var(cm);
3021 return; 3042 return;
3022 } 3043 }
3023 3044
@@ -3032,6 +3053,7 @@ void synchronize_sched_expedited(void)
3032 /* CPU hotplug operation in flight, use normal GP. */ 3053 /* CPU hotplug operation in flight, use normal GP. */
3033 wait_rcu_gp(call_rcu_sched); 3054 wait_rcu_gp(call_rcu_sched);
3034 atomic_long_inc(&rsp->expedited_normal); 3055 atomic_long_inc(&rsp->expedited_normal);
3056 free_cpumask_var(cm);
3035 return; 3057 return;
3036 } 3058 }
3037 snap = atomic_long_read(&rsp->expedited_start); 3059 snap = atomic_long_read(&rsp->expedited_start);
@@ -3039,6 +3061,9 @@ void synchronize_sched_expedited(void)
3039 } 3061 }
3040 atomic_long_inc(&rsp->expedited_stoppedcpus); 3062 atomic_long_inc(&rsp->expedited_stoppedcpus);
3041 3063
3064all_cpus_idle:
3065 free_cpumask_var(cm);
3066
3042 /* 3067 /*
3043 * Everyone up to our most recent fetch is covered by our grace 3068 * Everyone up to our most recent fetch is covered by our grace
3044 * period. Update the counter, but only if our work is still 3069 * period. Update the counter, but only if our work is still