aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sched.c')
-rw-r--r--kernel/sched.c40
1 files changed, 3 insertions, 37 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index f1d577a0a8ab..e9c6d798831a 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -8953,14 +8953,6 @@ static atomic_t synchronize_sched_expedited_count = ATOMIC_INIT(0);
8953 8953
8954static int synchronize_sched_expedited_cpu_stop(void *data) 8954static int synchronize_sched_expedited_cpu_stop(void *data)
8955{ 8955{
8956 static DEFINE_SPINLOCK(done_mask_lock);
8957 struct cpumask *done_mask = data;
8958
8959 if (done_mask) {
8960 spin_lock(&done_mask_lock);
8961 cpumask_set_cpu(smp_processor_id(), done_mask);
8962 spin_unlock(&done_mask_lock);
8963 }
8964 return 0; 8956 return 0;
8965} 8957}
8966 8958
@@ -8976,55 +8968,29 @@ static int synchronize_sched_expedited_cpu_stop(void *data)
8976 */ 8968 */
8977void synchronize_sched_expedited(void) 8969void synchronize_sched_expedited(void)
8978{ 8970{
8979 cpumask_var_t done_mask_var;
8980 struct cpumask *done_mask = NULL;
8981 int snap, trycount = 0; 8971 int snap, trycount = 0;
8982 8972
8983 /*
8984 * done_mask is used to check that all cpus actually have
8985 * finished running the stopper, which is guaranteed by
8986 * stop_cpus() if it's called with cpu hotplug blocked. Keep
8987 * the paranoia for now but it's best effort if cpumask is off
8988 * stack.
8989 */
8990 if (zalloc_cpumask_var(&done_mask_var, GFP_ATOMIC))
8991 done_mask = done_mask_var;
8992
8993 smp_mb(); /* ensure prior mod happens before capturing snap. */ 8973 smp_mb(); /* ensure prior mod happens before capturing snap. */
8994 snap = atomic_read(&synchronize_sched_expedited_count) + 1; 8974 snap = atomic_read(&synchronize_sched_expedited_count) + 1;
8995 get_online_cpus(); 8975 get_online_cpus();
8996 while (try_stop_cpus(cpu_online_mask, 8976 while (try_stop_cpus(cpu_online_mask,
8997 synchronize_sched_expedited_cpu_stop, 8977 synchronize_sched_expedited_cpu_stop,
8998 done_mask) == -EAGAIN) { 8978 NULL) == -EAGAIN) {
8999 put_online_cpus(); 8979 put_online_cpus();
9000 if (trycount++ < 10) 8980 if (trycount++ < 10)
9001 udelay(trycount * num_online_cpus()); 8981 udelay(trycount * num_online_cpus());
9002 else { 8982 else {
9003 synchronize_sched(); 8983 synchronize_sched();
9004 goto free_out; 8984 return;
9005 } 8985 }
9006 if (atomic_read(&synchronize_sched_expedited_count) - snap > 0) { 8986 if (atomic_read(&synchronize_sched_expedited_count) - snap > 0) {
9007 smp_mb(); /* ensure test happens before caller kfree */ 8987 smp_mb(); /* ensure test happens before caller kfree */
9008 goto free_out; 8988 return;
9009 } 8989 }
9010 get_online_cpus(); 8990 get_online_cpus();
9011 } 8991 }
9012 atomic_inc(&synchronize_sched_expedited_count); 8992 atomic_inc(&synchronize_sched_expedited_count);
9013 if (done_mask)
9014 cpumask_xor(done_mask, done_mask, cpu_online_mask);
9015 put_online_cpus(); 8993 put_online_cpus();
9016
9017 /* paranoia - this can't happen */
9018 if (done_mask && cpumask_weight(done_mask)) {
9019 char buf[80];
9020
9021 cpulist_scnprintf(buf, sizeof(buf), done_mask);
9022 WARN_ONCE(1, "synchronize_sched_expedited: cpu online and done masks disagree on %d cpus: %s\n",
9023 cpumask_weight(done_mask), buf);
9024 synchronize_sched();
9025 }
9026free_out:
9027 free_cpumask_var(done_mask_var);
9028} 8994}
9029EXPORT_SYMBOL_GPL(synchronize_sched_expedited); 8995EXPORT_SYMBOL_GPL(synchronize_sched_expedited);
9030 8996