aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir@xen.org>2011-01-14 14:16:04 +0000
committerKeir Fraser <keir@xen.org>2011-01-14 14:16:04 +0000
commit28c7ad54f50ec385f5ae6f5323801e8c0dd8b2cf (patch)
treef22b085c68dc309b1203e2bff668220bc611c339
parent22154402c7d7c358024c9aeaa7506d78f35363ae (diff)
downloadxen-28c7ad54f50ec385f5ae6f5323801e8c0dd8b2cf.tar.gz
xen-28c7ad54f50ec385f5ae6f5323801e8c0dd8b2cf.tar.bz2
xen-28c7ad54f50ec385f5ae6f5323801e8c0dd8b2cf.zip
stop_machine: Allow specified function to run on all CPUs.
Signed-off-by: Keir Fraser <keir@xen.org>
-rw-r--r--xen/common/stop_machine.c15
-rw-r--r--xen/include/xen/stop_machine.h2
2 files changed, 13 insertions, 4 deletions
diff --git a/xen/common/stop_machine.c b/xen/common/stop_machine.c
index 31d5c6fff7..9bf271452d 100644
--- a/xen/common/stop_machine.c
+++ b/xen/common/stop_machine.c
@@ -61,6 +61,10 @@ static void stopmachine_set_state(enum stopmachine_state state)
atomic_set(&stopmachine_data.done, 0);
smp_wmb();
stopmachine_data.state = state;
+}
+
+static void stopmachine_wait_state(void)
+{
while ( atomic_read(&stopmachine_data.done) != stopmachine_data.nr_cpus )
cpu_relax();
}
@@ -101,16 +105,20 @@ int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu)
tasklet_schedule_on_cpu(&per_cpu(stopmachine_tasklet, i), i);
stopmachine_set_state(STOPMACHINE_PREPARE);
+ stopmachine_wait_state();
local_irq_disable();
stopmachine_set_state(STOPMACHINE_DISABLE_IRQ);
+ stopmachine_wait_state();
- if ( cpu == smp_processor_id() )
- stopmachine_data.fn_result = (*fn)(data);
stopmachine_set_state(STOPMACHINE_INVOKE);
+ if ( (cpu == smp_processor_id()) || (cpu == NR_CPUS) )
+ stopmachine_data.fn_result = (*fn)(data);
+ stopmachine_wait_state();
ret = stopmachine_data.fn_result;
stopmachine_set_state(STOPMACHINE_EXIT);
+ stopmachine_wait_state();
local_irq_enable();
spin_unlock(&stopmachine_lock);
@@ -140,7 +148,8 @@ static void stopmachine_action(unsigned long cpu)
local_irq_disable();
break;
case STOPMACHINE_INVOKE:
- if ( stopmachine_data.fn_cpu == smp_processor_id() )
+ if ( (stopmachine_data.fn_cpu == smp_processor_id()) ||
+ (stopmachine_data.fn_cpu == NR_CPUS) )
stopmachine_data.fn_result =
stopmachine_data.fn(stopmachine_data.fn_data);
break;
diff --git a/xen/include/xen/stop_machine.h b/xen/include/xen/stop_machine.h
index 7d4506869f..c63da1b309 100644
--- a/xen/include/xen/stop_machine.h
+++ b/xen/include/xen/stop_machine.h
@@ -5,7 +5,7 @@
* stop_machine_run: freeze the machine on all CPUs and run this function
* @fn: the function to run
* @data: the data ptr for the @fn()
- * @cpu: the cpu to run @fn() on (or any, if @cpu == NR_CPUS).
+ * @cpu: the cpu to run @fn() on (or all, if @cpu == NR_CPUS).
*
* Description: This causes every other cpu to enter a safe point, with
* each of which disables interrupts, and finally interrupts are disabled