diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 40 |
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 | ||
8954 | static int synchronize_sched_expedited_cpu_stop(void *data) | 8954 | static 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 | */ |
8977 | void synchronize_sched_expedited(void) | 8969 | void 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 | } | ||
9026 | free_out: | ||
9027 | free_cpumask_var(done_mask_var); | ||
9028 | } | 8994 | } |
9029 | EXPORT_SYMBOL_GPL(synchronize_sched_expedited); | 8995 | EXPORT_SYMBOL_GPL(synchronize_sched_expedited); |
9030 | 8996 | ||