diff options
-rw-r--r-- | kernel/rcu/tree.c | 27 |
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 | */ |
2951 | void synchronize_sched_expedited(void) | 2951 | void 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 | ||
3064 | all_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 |