[POWERPC] Fix smp_call_function to be preempt-safe
smp_call_function_map() was not safe against preemption to another cpu: its test for removing self from map was outside the spinlock. Rearrange it a little to fix that. smp_call_function_single() was also wrong: now get_cpu() before excluding self, as other architectures do. Signed-off-by: Hugh Dickins <hugh@veritas.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
d257905323
commit
d3fdaed9e9
|
@ -201,13 +201,6 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic,
|
|||
/* Can deadlock when called with interrupts disabled */
|
||||
WARN_ON(irqs_disabled());
|
||||
|
||||
/* remove 'self' from the map */
|
||||
if (cpu_isset(smp_processor_id(), map))
|
||||
cpu_clear(smp_processor_id(), map);
|
||||
|
||||
/* sanity check the map, remove any non-online processors. */
|
||||
cpus_and(map, map, cpu_online_map);
|
||||
|
||||
if (unlikely(smp_ops == NULL))
|
||||
return ret;
|
||||
|
||||
|
@ -222,10 +215,17 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic,
|
|||
/* Must grab online cpu count with preempt disabled, otherwise
|
||||
* it can change. */
|
||||
num_cpus = num_online_cpus() - 1;
|
||||
if (!num_cpus || cpus_empty(map)) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
if (!num_cpus)
|
||||
goto done;
|
||||
|
||||
/* remove 'self' from the map */
|
||||
if (cpu_isset(smp_processor_id(), map))
|
||||
cpu_clear(smp_processor_id(), map);
|
||||
|
||||
/* sanity check the map, remove any non-online processors. */
|
||||
cpus_and(map, map, cpu_online_map);
|
||||
if (cpus_empty(map))
|
||||
goto done;
|
||||
|
||||
call_data = &data;
|
||||
smp_wmb();
|
||||
|
@ -263,6 +263,7 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic,
|
|||
}
|
||||
}
|
||||
|
||||
done:
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
|
@ -282,16 +283,17 @@ EXPORT_SYMBOL(smp_call_function);
|
|||
int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic,
|
||||
int wait)
|
||||
{
|
||||
cpumask_t map=CPU_MASK_NONE;
|
||||
cpumask_t map = CPU_MASK_NONE;
|
||||
int ret = -EBUSY;
|
||||
|
||||
if (!cpu_online(cpu))
|
||||
return -EINVAL;
|
||||
|
||||
if (cpu == smp_processor_id())
|
||||
return -EBUSY;
|
||||
|
||||
cpu_set(cpu, map);
|
||||
return smp_call_function_map(func,info,nonatomic,wait,map);
|
||||
if (cpu != get_cpu())
|
||||
ret = smp_call_function_map(func,info,nonatomic,wait,map);
|
||||
put_cpu();
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(smp_call_function_single);
|
||||
|
||||
|
|
Loading…
Reference in New Issue