Clean up and fix domain_pause and friends. Synchronous
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 26 Aug 2005 09:29:54 +0000 (09:29 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 26 Aug 2005 09:29:54 +0000 (09:29 +0000)
pause should not only wait for the running flag to clear,
but also for the scheduler lock to be released. Also get
rid of some unused sync_lazy_execstate functions.

Signed-off-by: Keir Fraser <keir@xensource.com>
13 files changed:
xen/arch/ia64/linux-xen/irq_ia64.c
xen/arch/ia64/patch/linux-2.6.11/irq_ia64.c
xen/arch/ia64/patch/linux-2.6.7/irq_ia64.c
xen/arch/ia64/patch/linux-2.6.7/time.c
xen/arch/ia64/xenirq.c
xen/arch/ia64/xenmisc.c
xen/arch/ia64/xentime.c
xen/arch/x86/audit.c
xen/arch/x86/domain.c
xen/common/domain.c
xen/common/schedule.c
xen/include/asm-x86/mm.h
xen/include/xen/sched.h

index 478f3343eeeaeddba3f03488b64c11f59eb0188d..a3762df2274660bc801408254fe94c3e9e37bea4 100644 (file)
@@ -265,7 +265,7 @@ vmx_ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
         */
        vmx_irq_exit();
        if ( wake_dom0 && current != dom0 ) 
-               domain_wake(dom0->vcpu[0]);
+               vcpu_wake(dom0->vcpu[0]);
 }
 #endif
 
index 473db52b265ebae6ec1ec56e25a7b69334e58339..303f7e0d35b7da2b032394b6db9ca0c5fd9c1e10 100644 (file)
 +       */
 +      vmx_irq_exit();
 +      if ( wake_dom0 && current != dom0 ) 
-+              domain_wake(dom0->vcpu[0]);
++              vcpu_wake(dom0->vcpu[0]);
 +}
 +#endif
 +
index 8d991ddd2cf84e089ed8f60b7f6ea0cf03a95889..2e96676814a909fb370955ad13799ad5df4ad97e 100644 (file)
@@ -73,7 +73,7 @@
 +#endif
 +              //FIXME: TEMPORARY HACK!!!!
 +              vcpu_pend_interrupt(dom0->vcpu[0],vector);
-+              domain_wake(dom0->vcpu[0]);
++              vcpu_wake(dom0->vcpu[0]);
 +      }
 +      else
 +#endif
index 1b6263ce4f6ff6dab94fab9d4c29aaacc80fc3b5..27b01da8c2bd605e171289e982743e4f42e33c86 100644 (file)
 +      if (domain0_ready && vcpu_timer_expired(dom0->vcpu[0])) {
 +              vcpu_pend_timer(dom0->vcpu[0]);
 +              //vcpu_set_next_timer(dom0->vcpu[0]);
-+              domain_wake(dom0->vcpu[0]);
++              vcpu_wake(dom0->vcpu[0]);
 +      }
 +      if (!is_idle_task(current->domain) && current->domain != dom0) {
 +              if (vcpu_timer_expired(current)) {
 +                      vcpu_pend_timer(current);
 +                      // ensure another timer interrupt happens even if domain doesn't
 +                      vcpu_set_next_timer(current);
-+                      domain_wake(current);
++                      vcpu_wake(current);
 +              }
 +      }
 +      raise_actimer_softirq();
index 5bf09171c832362813a9971cce4817701542ddc4..296cd3267b94c978ace121b4fc139e77de8c4d4b 100644 (file)
@@ -50,7 +50,7 @@ xen_do_IRQ(ia64_vector vector)
 #endif
                //FIXME: TEMPORARY HACK!!!!
                vcpu_pend_interrupt(dom0->vcpu[0],vector);
-               domain_wake(dom0->vcpu[0]);
+               vcpu_wake(dom0->vcpu[0]);
                return(1);
        }
        return(0);
index 2fc45e85dbe0f0c71f4489bdeb5dd155aa3fce25..c76a93eca8a8d538377316555a145064609c86ac 100644 (file)
@@ -59,8 +59,6 @@ platform_is_hp_ski(void)
 /* calls in xen/common code that are unused on ia64 */
 
 void sync_lazy_execstate_cpu(unsigned int cpu) {}
-void sync_lazy_execstate_mask(cpumask_t mask) {}
-void sync_lazy_execstate_all(void) {}
 
 #ifdef CONFIG_VTI
 int grant_table_create(struct domain *d) { return 0; }
index 25b220cbf9b7a897ea94c8d810d7d5b6d0f60a28..843b9f33158eb32be06b359f7ab22f0f5872e05f 100644 (file)
@@ -162,14 +162,14 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
        if (domain0_ready && vcpu_timer_expired(dom0->vcpu[0])) {
                vcpu_pend_timer(dom0->vcpu[0]);
                //vcpu_set_next_timer(dom0->vcpu[0]);
-               domain_wake(dom0->vcpu[0]);
+               vcpu_wake(dom0->vcpu[0]);
        }
        if (!is_idle_task(current->domain) && current->domain != dom0) {
                if (vcpu_timer_expired(current)) {
                        vcpu_pend_timer(current);
                        // ensure another timer interrupt happens even if domain doesn't
                        vcpu_set_next_timer(current);
-                       domain_wake(current);
+                       vcpu_wake(current);
                }
        }
        raise_actimer_softirq();
index fee6312155f9c49b38949ccf516934d36e781a63..97e48ef77cf7ff0e21ff5063bc324793dc95623e 100644 (file)
@@ -735,7 +735,6 @@ void _audit_domain(struct domain *d, int flags)
 
     if ( d != current->domain )
         domain_pause(d);
-    sync_lazy_execstate_all();
 
     // Maybe we should just be using BIGLOCK?
     //
index 4f4187dda7fcddf1432a5cd6cc59b07ce2f9b45f..db1d630e6423920991c9bdc224ed98a830024385 100644 (file)
@@ -888,24 +888,14 @@ int __sync_lazy_execstate(void)
 void sync_lazy_execstate_cpu(unsigned int cpu)
 {
     if ( cpu == smp_processor_id() )
+    {
         (void)__sync_lazy_execstate();
+    }
     else
+    {
+        /* Other cpus call __sync_lazy_execstate from flush ipi handler. */
         flush_tlb_mask(cpumask_of_cpu(cpu));
-}
-
-void sync_lazy_execstate_mask(cpumask_t mask)
-{
-    if ( cpu_isset(smp_processor_id(), mask) )
-        (void)__sync_lazy_execstate();
-    /* Other cpus call __sync_lazy_execstate from flush ipi handler. */
-    flush_tlb_mask(mask);
-}
-
-void sync_lazy_execstate_all(void)
-{
-    __sync_lazy_execstate();
-    /* Other cpus call __sync_lazy_execstate from flush ipi handler. */
-    flush_tlb_mask(cpu_online_map);
+    }
 }
 
 unsigned long __hypercall_create_continuation(
index b939d90f77099a8aa56c5bfba29bdc026b134c0d..713e5bb3ff11983851c18ad58acfb94e66c01eb6 100644 (file)
@@ -152,10 +152,7 @@ static void domain_shutdown_finalise(void)
 
     /* Make sure that every vcpu is descheduled before we finalise. */
     for_each_vcpu ( d, v )
-        while ( test_bit(_VCPUF_running, &v->vcpu_flags) )
-            cpu_relax();
-
-    sync_lazy_execstate_mask(d->cpumask);
+        vcpu_sleep_sync(v);
     BUG_ON(!cpus_empty(d->cpumask));
 
     sync_pagetable_state(d);
@@ -209,7 +206,7 @@ void domain_shutdown(u8 reason)
 
     /* Put every vcpu to sleep, but don't wait (avoids inter-vcpu deadlock). */
     for_each_vcpu ( d, v )
-        domain_sleep_nosync(v);
+        vcpu_sleep_nosync(v);
 }
 
 
@@ -226,7 +223,7 @@ void domain_pause_for_debugger(void)
     for_each_vcpu ( d, v )
     {
         set_bit(_VCPUF_ctrl_pause, &v->vcpu_flags);
-        domain_sleep_nosync(v);
+        vcpu_sleep_nosync(v);
     }
 
     send_guest_virq(dom0->vcpu[0], VIRQ_DEBUGGER);
@@ -275,7 +272,7 @@ void vcpu_pause(struct vcpu *v)
 {
     BUG_ON(v == current);
     atomic_inc(&v->pausecnt);
-    domain_sleep_sync(v);
+    vcpu_sleep_sync(v);
 }
 
 void domain_pause(struct domain *d)
@@ -286,7 +283,7 @@ void domain_pause(struct domain *d)
     {
         BUG_ON(v == current);
         atomic_inc(&v->pausecnt);
-        domain_sleep_sync(v);
+        vcpu_sleep_sync(v);
     }
 }
 
@@ -294,7 +291,7 @@ void vcpu_unpause(struct vcpu *v)
 {
     BUG_ON(v == current);
     if ( atomic_dec_and_test(&v->pausecnt) )
-        domain_wake(v);
+        vcpu_wake(v);
 }
 
 void domain_unpause(struct domain *d)
@@ -313,7 +310,7 @@ void domain_pause_by_systemcontroller(struct domain *d)
     {
         BUG_ON(v == current);
         if ( !test_and_set_bit(_VCPUF_ctrl_pause, &v->vcpu_flags) )
-            domain_sleep_sync(v);
+            vcpu_sleep_sync(v);
     }
 }
 
@@ -324,7 +321,7 @@ void domain_unpause_by_systemcontroller(struct domain *d)
     for_each_vcpu ( d, v )
     {
         if ( test_and_clear_bit(_VCPUF_ctrl_pause, &v->vcpu_flags) )
-            domain_wake(v);
+            vcpu_wake(v);
     }
 }
 
@@ -413,7 +410,7 @@ long do_boot_vcpu(unsigned long vcpu, struct vcpu_guest_context *ctxt)
 
     /* domain_unpause_by_systemcontroller */
     if ( test_and_clear_bit(_VCPUF_ctrl_pause, &v->vcpu_flags) )
-        domain_wake(v);
+        vcpu_wake(v);
 
     xfree(c);
     return 0;
index 1a8eb12aa03cb834c222407bd5d0be1c98cde437..3cec1097278fb12add7266239e30c5acd474269f 100644 (file)
@@ -193,7 +193,7 @@ void sched_rem_domain(struct vcpu *v)
     TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id);
 }
 
-void domain_sleep_nosync(struct vcpu *v)
+void vcpu_sleep_nosync(struct vcpu *v)
 {
     unsigned long flags;
 
@@ -205,18 +205,25 @@ void domain_sleep_nosync(struct vcpu *v)
     TRACE_2D(TRC_SCHED_SLEEP, v->domain->domain_id, v->vcpu_id);
 } 
 
-void domain_sleep_sync(struct vcpu *v)
+void vcpu_sleep_sync(struct vcpu *v)
 {
-    domain_sleep_nosync(v);
-
-    while ( test_bit(_VCPUF_running, &v->vcpu_flags) && !domain_runnable(v) )
+    vcpu_sleep_nosync(v);
+
+    /*
+     * We can be sure that the VCPU is finally descheduled after the running
+     * flag is cleared and the scheduler lock is released.
+     */
+    while ( test_bit(_VCPUF_running, &v->vcpu_flags)
+            && !domain_runnable(v)
+            && spin_is_locked(&schedule_data[v->processor].schedule_lock) )
         cpu_relax();
 
+    /* Counteract lazy context switching. */
     if ( cpu_isset(v->processor, v->domain->cpumask) )
         sync_lazy_execstate_cpu(v->processor);
 }
 
-void domain_wake(struct vcpu *v)
+void vcpu_wake(struct vcpu *v)
 {
     unsigned long flags;
 
@@ -293,7 +300,7 @@ static long do_vcpu_up(int vcpu)
         return -ESRCH;
     clear_bit(_VCPUF_down, &target->vcpu_flags);
     /* wake vcpu */
-    domain_wake(target);
+    vcpu_wake(target);
 
     return 0;
 }
@@ -457,10 +464,10 @@ long sched_adjdom(struct sched_adjdom_cmd *cmd)
                 }
             }
         }
-    } while (!succ);
-    //spin_lock_irq(&schedule_data[d->vcpu[0]->processor].schedule_lock);
+    } while ( !succ );
+
     SCHED_OP(adjdom, d, cmd);
-    //spin_unlock_irq(&schedule_data[d->vcpu[0]->processor].schedule_lock);
+
     for (cpu = 0; cpu < NR_CPUS; cpu++)
         if (__get_cpu_bit(cpu, have_lock))
             spin_unlock(&schedule_data[cpu].schedule_lock);
@@ -520,7 +527,8 @@ static void __enter_scheduler(void)
     perfc_incrc(sched_ctx);
 
 #if defined(WAKE_HISTO)
-    if ( !is_idle_task(next->domain) && next->wokenup ) {
+    if ( !is_idle_task(next->domain) && next->wokenup )
+    {
         ulong diff = (ulong)(now - next->wokenup);
         diff /= (ulong)MILLISECS(1);
         if (diff <= BUCKETS-2)  schedule_data[cpu].hist[diff]++;
index 9147b631bd861fdabc1a27865e11c59d12d12b63..adab08a3ee046735f1e1ced2d6f255ed5f030764 100644 (file)
@@ -370,6 +370,8 @@ int new_guest_cr3(unsigned long pfn);
 
 void propagate_page_fault(unsigned long addr, u16 error_code);
 
+extern int __sync_lazy_execstate(void);
+
 /*
  * Caller must own d's BIGLOCK, is responsible for flushing the TLB, and must 
  * hold a reference to the page.
index e0ea2f756d4b1b59cceb8e13fd332e89de7852d5..2d93f7576d7491150cf5e97ab146034041274516 100644 (file)
@@ -245,18 +245,15 @@ void sched_rem_domain(struct vcpu *);
 long sched_ctl(struct sched_ctl_cmd *);
 long sched_adjdom(struct sched_adjdom_cmd *);
 int  sched_id();
-void domain_wake(struct vcpu *d);
-void domain_sleep_nosync(struct vcpu *d);
-void domain_sleep_sync(struct vcpu *d);
+void vcpu_wake(struct vcpu *d);
+void vcpu_sleep_nosync(struct vcpu *d);
+void vcpu_sleep_sync(struct vcpu *d);
 
 /*
- * Force loading of currently-executing domain state on the specified set
- * of CPUs. This is used to counteract lazy state switching where required.
+ * Force loading of currently-executing domain state on the specified CPU.
+ * This is used to counteract lazy state switching where required.
  */
 extern void sync_lazy_execstate_cpu(unsigned int cpu);
-extern void sync_lazy_execstate_mask(cpumask_t mask);
-extern void sync_lazy_execstate_all(void);
-extern int __sync_lazy_execstate(void);
 
 /*
  * Called by the scheduler to switch to another VCPU. On entry, although
@@ -268,7 +265,7 @@ extern int __sync_lazy_execstate(void);
  * The callee must ensure that the local CPU is no longer running in @prev's
  * context, and that the context is saved to memory, before returning.
  * Alternatively, if implementing lazy context switching, it suffices to ensure
- * that invoking __sync_lazy_execstate() will switch and commit @prev's state.
+ * that invoking sync_lazy_execstate() will switch and commit @prev's state.
  */
 extern void context_switch(
     struct vcpu *prev, 
@@ -287,7 +284,8 @@ extern void context_switch_finalise(
 extern void continue_running(
     struct vcpu *same);
 
-int idle_cpu(int cpu); /* Is CPU 'cpu' idle right now? */
+/* Is CPU 'cpu' idle right now? */
+int idle_cpu(int cpu);
 
 void startup_cpu_idle_loop(void);
 
@@ -410,7 +408,7 @@ void cpu_init(void);
 static inline void vcpu_unblock(struct vcpu *v)
 {
     if ( test_and_clear_bit(_VCPUF_blocked, &v->vcpu_flags) )
-        domain_wake(v);
+        vcpu_wake(v);
 }
 
 #define IS_PRIV(_d)                                         \