# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1243502355 -3600
# Node ID 0e111bfd22d06ee0f05baedabc7928c3dfaf4c0a
# Parent e95c4611a0ae38eadcc29268ac7f5e39457b651e
x86: Fix flush_area_mask() and on_selected_cpus() to not race updates
of the supplied cpumask (which is now passed by reference).
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/smp.c | 68 +++++++++++++++++++++++++----------------------------
1 files changed, 33 insertions(+), 35 deletions(-)
diff -r e95c4611a0ae -r 0e111bfd22d0 xen/arch/x86/smp.c
--- a/xen/arch/x86/smp.c Thu May 28 10:06:01 2009 +0100
+++ b/xen/arch/x86/smp.c Thu May 28 10:19:15 2009 +0100
@@ -192,7 +192,7 @@ void flush_area_mask(const cpumask_t *ma
cpus_andnot(flush_cpumask, *mask, *cpumask_of(smp_processor_id()));
flush_va = va;
flush_flags = flags;
- send_IPI_mask(mask, INVALIDATE_TLB_VECTOR);
+ send_IPI_mask(&flush_cpumask, INVALIDATE_TLB_VECTOR);
while ( !cpus_empty(flush_cpumask) )
cpu_relax();
spin_unlock(&flush_lock);
@@ -223,18 +223,16 @@ void smp_send_event_check_mask(const cpu
* Structure and data for smp_call_function()/on_selected_cpus().
*/
-struct call_data_struct {
+static void __smp_call_function_interrupt(void);
+static DEFINE_SPINLOCK(call_lock);
+static struct call_data_struct {
void (*func) (void *info);
void *info;
int wait;
atomic_t started;
atomic_t finished;
- const cpumask_t *selected;
-};
-
-static DEFINE_SPINLOCK(call_lock);
-static struct call_data_struct *call_data;
-static void __smp_call_function_interrupt(void);
+ cpumask_t selected;
+} call_data;
int smp_call_function(
void (*func) (void *info),
@@ -252,39 +250,39 @@ int on_selected_cpus(
void *info,
int wait)
{
- struct call_data_struct data;
- unsigned int nr_cpus = cpus_weight(*selected);
+ unsigned int nr_cpus;
ASSERT(local_irq_is_enabled());
+ spin_lock(&call_lock);
+
+ call_data.selected = *selected;
+
+ nr_cpus = cpus_weight(call_data.selected);
if ( nr_cpus == 0 )
- return 0;
-
- data.func = func;
- data.info = info;
- data.wait = wait;
- atomic_set(&data.started, 0);
- atomic_set(&data.finished, 0);
- data.selected = selected;
-
- spin_lock(&call_lock);
-
- call_data = &data;
-
- send_IPI_mask(selected, CALL_FUNCTION_VECTOR);
-
- if ( cpu_isset(smp_processor_id(), *call_data->selected) )
+ goto out;
+
+ call_data.func = func;
+ call_data.info = info;
+ call_data.wait = wait;
+ atomic_set(&call_data.started, 0);
+ atomic_set(&call_data.finished, 0);
+
+ send_IPI_mask(&call_data.selected, CALL_FUNCTION_VECTOR);
+
+ if ( cpu_isset(smp_processor_id(), call_data.selected) )
{
local_irq_disable();
__smp_call_function_interrupt();
local_irq_enable();
}
- while ( atomic_read(wait ? &data.finished : &data.started) != nr_cpus )
+ while ( atomic_read(wait ? &call_data.finished : &call_data.started)
+ != nr_cpus )
cpu_relax();
+ out:
spin_unlock(&call_lock);
-
return 0;
}
@@ -345,24 +343,24 @@ fastcall void smp_event_check_interrupt(
static void __smp_call_function_interrupt(void)
{
- void (*func)(void *info) = call_data->func;
- void *info = call_data->info;
-
- if ( !cpu_isset(smp_processor_id(), *call_data->selected) )
+ void (*func)(void *info) = call_data.func;
+ void *info = call_data.info;
+
+ if ( !cpu_isset(smp_processor_id(), call_data.selected) )
return;
irq_enter();
- if ( call_data->wait )
+ if ( call_data.wait )
{
(*func)(info);
mb();
- atomic_inc(&call_data->finished);
+ atomic_inc(&call_data.finished);
}
else
{
mb();
- atomic_inc(&call_data->started);
+ atomic_inc(&call_data.started);
(*func)(info);
}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|