]> xenbits.xensource.com Git - xen.git/commitdiff
stopmachine: Implement using tasklets rather than a softirq.
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 19 Apr 2010 10:47:59 +0000 (11:47 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 19 Apr 2010 10:47:59 +0000 (11:47 +0100)
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/ia64/xen/domain.c
xen/arch/x86/domain.c
xen/common/stop_machine.c
xen/include/xen/sched.h
xen/include/xen/softirq.h

index 93e302f1cc61df6742bd4dbe7bfa5372ac826b46..7e48b66d40bcd4c3a18ec110b1118fe3cad24f76 100644 (file)
@@ -2343,6 +2343,10 @@ void machine_halt(void)
        while(1);
 }
 
+void sync_local_execstate(void)
+{
+}
+
 void sync_vcpu_execstate(struct vcpu *v)
 {
 //     __ia64_save_fpu(v->arch._thread.fph);
index 07ec8b386defba41e05044ada48859115feb249f..070810b0af5a65d82fb31f3222d576d1cac2e282 100644 (file)
@@ -1509,6 +1509,11 @@ int __sync_lazy_execstate(void)
     return switch_required;
 }
 
+void sync_local_execstate(void)
+{
+    (void)__sync_lazy_execstate();
+}
+
 void sync_vcpu_execstate(struct vcpu *v)
 {
     if ( cpu_isset(smp_processor_id(), v->vcpu_dirty_cpumask) )
index f7d9071b6668434e7a8511090a472860a0184a3b..99604cde328619159f2bb66677e967e3b0fbba00 100644 (file)
@@ -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);
index 3626b98c3a472465b0c8480c89d6b87d782a186c..15f64fc97e14dc2ec0f04373839aacb408bd7b38 100644 (file)
@@ -480,6 +480,9 @@ void vcpu_sleep_sync(struct vcpu *d);
  */
 void sync_vcpu_execstate(struct vcpu *v);
 
+/* As above, for any lazy state being held on the local CPU. */
+void sync_local_execstate(void);
+
 /*
  * Called by the scheduler to switch to another VCPU. This function must
  * call context_saved(@prev) when the local CPU is no longer running in
index 43289cea8df446c329f0903b5d573c58df146a52..1408a4cb156aaedfbbb78cb539939d02da70d875 100644 (file)
@@ -8,7 +8,6 @@ enum {
     NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ,
     PAGE_SCRUB_SOFTIRQ,
     RCU_SOFTIRQ,
-    STOPMACHINE_SOFTIRQ,
     NR_COMMON_SOFTIRQS
 };