diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-04-19 11:47:59 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-04-19 11:47:59 +0100 |
commit | 1f437c62318cb6bc81c5f7bbc73a472cc4255a92 (patch) | |
tree | e211ee2c7c6edabd9903469d13ec269926a1a924 /xen/common/stop_machine.c | |
parent | 5fa9cbb8057b000f7e47f1305408fc0865fa2c23 (diff) | |
download | xen-1f437c62318cb6bc81c5f7bbc73a472cc4255a92.tar.gz xen-1f437c62318cb6bc81c5f7bbc73a472cc4255a92.tar.bz2 xen-1f437c62318cb6bc81c5f7bbc73a472cc4255a92.zip |
stopmachine: Implement using tasklets rather than a softirq.
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 | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/xen/common/stop_machine.c b/xen/common/stop_machine.c index f7d9071b66..99604cde32 100644 --- a/xen/common/stop_machine.c +++ b/xen/common/stop_machine.c @@ -24,7 +24,7 @@ #include <xen/init.h> #include <xen/sched.h> #include <xen/spinlock.h> -#include <xen/softirq.h> +#include <xen/tasklet.h> #include <xen/stop_machine.h> #include <xen/errno.h> #include <xen/smp.h> @@ -51,6 +51,7 @@ struct stopmachine_data { void *fn_data; }; +static DEFINE_PER_CPU(struct tasklet, stopmachine_tasklet); static struct stopmachine_data stopmachine_data; static DEFINE_SPINLOCK(stopmachine_lock); @@ -81,10 +82,7 @@ int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) return (*fn)(data); } - /* Note: We shouldn't spin on lock when it's held by others since others - * is expecting this cpus to enter softirq context. Or else deadlock - * is caused. - */ + /* Must not spin here as the holder will expect us to be descheduled. */ if ( !spin_trylock(&stopmachine_lock) ) return -EBUSY; @@ -98,8 +96,9 @@ int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) smp_wmb(); for_each_cpu_mask ( i, allbutself ) - cpu_raise_softirq(i, STOPMACHINE_SOFTIRQ); + tasklet_schedule_on_cpu(&per_cpu(stopmachine_tasklet, i), i); + sync_local_execstate(); stopmachine_set_state(STOPMACHINE_PREPARE); local_irq_disable(); @@ -118,10 +117,11 @@ int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) return ret; } -static void stopmachine_softirq(void) +static void stopmachine_action(unsigned long unused) { enum stopmachine_state state = STOPMACHINE_START; + sync_local_execstate(); smp_mb(); while ( state != STOPMACHINE_EXIT ) @@ -153,7 +153,10 @@ static void stopmachine_softirq(void) static int __init cpu_stopmachine_init(void) { - open_softirq(STOPMACHINE_SOFTIRQ, stopmachine_softirq); + unsigned int cpu; + for_each_possible_cpu ( cpu ) + tasklet_init(&per_cpu(stopmachine_tasklet, cpu), + stopmachine_action, 0); return 0; } __initcall(cpu_stopmachine_init); |