diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-05-14 17:07:52 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-05-14 17:07:52 +0100 |
commit | 27c31d386746bea3daa5b3733c9f986a9c3cccc3 (patch) | |
tree | 64ef675ed9b4c0836ab9076b7280e88a64f5bb16 /xen/common/stop_machine.c | |
parent | 2e4146ddc277d2ddd861646b8b1ba83182eb84bb (diff) | |
download | xen-27c31d386746bea3daa5b3733c9f986a9c3cccc3.tar.gz xen-27c31d386746bea3daa5b3733c9f986a9c3cccc3.tar.bz2 xen-27c31d386746bea3daa5b3733c9f986a9c3cccc3.zip |
Move cpu hotplug routines into common cpu.c file.
Also simplify the locking (reverting to use if spin_trylock, as
returning EBUSY/EAGAIN seems unavoidable after all). In particular
this should continue to ensure that stop_machine_run() does not have
cpu_online_map change under its feet.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/common/stop_machine.c')
-rw-r--r-- | xen/common/stop_machine.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/xen/common/stop_machine.c b/xen/common/stop_machine.c index 9f5dd1e799..70856505e3 100644 --- a/xen/common/stop_machine.c +++ b/xen/common/stop_machine.c @@ -28,6 +28,7 @@ #include <xen/stop_machine.h> #include <xen/errno.h> #include <xen/smp.h> +#include <xen/cpu.h> #include <asm/current.h> #include <asm/processor.h> @@ -72,19 +73,20 @@ int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) BUG_ON(!local_irq_is_enabled()); + /* cpu_online_map must not change. */ + if ( !get_cpu_maps() ) + return -EBUSY; + allbutself = cpu_online_map; cpu_clear(smp_processor_id(), allbutself); nr_cpus = cpus_weight(allbutself); - if ( nr_cpus == 0 ) - { - BUG_ON(cpu != smp_processor_id()); - return (*fn)(data); - } - /* Must not spin here as the holder will expect us to be descheduled. */ if ( !spin_trylock(&stopmachine_lock) ) + { + put_cpu_maps(); return -EBUSY; + } stopmachine_data.fn = fn; stopmachine_data.fn_data = data; @@ -113,13 +115,17 @@ int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) spin_unlock(&stopmachine_lock); + put_cpu_maps(); + return ret; } -static void stopmachine_action(unsigned long unused) +static void stopmachine_action(unsigned long cpu) { enum stopmachine_state state = STOPMACHINE_START; + BUG_ON(cpu != smp_processor_id()); + smp_mb(); while ( state != STOPMACHINE_EXIT ) |