aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/stop_machine.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-05-14 17:07:52 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-05-14 17:07:52 +0100
commit27c31d386746bea3daa5b3733c9f986a9c3cccc3 (patch)
tree64ef675ed9b4c0836ab9076b7280e88a64f5bb16 /xen/common/stop_machine.c
parent2e4146ddc277d2ddd861646b8b1ba83182eb84bb (diff)
downloadxen-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.c20
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 )