diff options
author | Keir Fraser <keir@xen.org> | 2011-01-14 14:16:04 +0000 |
---|---|---|
committer | Keir Fraser <keir@xen.org> | 2011-01-14 14:16:04 +0000 |
commit | 28c7ad54f50ec385f5ae6f5323801e8c0dd8b2cf (patch) | |
tree | f22b085c68dc309b1203e2bff668220bc611c339 | |
parent | 22154402c7d7c358024c9aeaa7506d78f35363ae (diff) | |
download | xen-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.c | 15 | ||||
-rw-r--r-- | xen/include/xen/stop_machine.h | 2 |
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 |