Add a new timer operation kill_timer(). Effectively the
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 13 Jan 2006 00:03:44 +0000 (01:03 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 13 Jan 2006 00:03:44 +0000 (01:03 +0100)
'opposite' of init_timer(), it marks the end of a timer's
lifetime. After this call the timer will not be pending,
its callback handler will not be running, and future calls
to set_timer() will silently fail.

Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/vmx.c
xen/common/sched_bvt.c
xen/common/schedule.c
xen/common/timer.c
xen/include/xen/timer.h

index f6a43848160fc35737734c6cfe80ddc126ba6ec7..6d6fa517646b562ec3ae1d7b1d7ce7a258bc9c21 100644 (file)
@@ -105,13 +105,11 @@ void vmx_relinquish_resources(struct vcpu *v)
     destroy_vmcs(&v->arch.arch_vmx);
     free_monitor_pagetable(v);
     vpit = &v->domain->arch.vmx_platform.vmx_pit;
-    if ( active_timer(&(vpit->pit_timer)) )
-        stop_timer(&vpit->pit_timer);
-    if ( active_timer(&v->arch.arch_vmx.hlt_timer) )
-        stop_timer(&v->arch.arch_vmx.hlt_timer);
+    kill_timer(&vpit->pit_timer);
+    kill_timer(&v->arch.arch_vmx.hlt_timer);
     if ( vmx_apic_support(v->domain) && (VLAPIC(v) != NULL) )
     {
-        stop_timer(&VLAPIC(v)->vlapic_timer);
+        kill_timer(&VLAPIC(v)->vlapic_timer);
         xfree(VLAPIC(v));
     }
 }
index 418909837b99c4233d7dc894a91be370daf134de..0a0f30d1a3e12714643fb5731f43c254d6b33b8f 100644 (file)
@@ -45,9 +45,9 @@ struct bvt_dom_info
                                              limits*/
     s32                 warp_value;       /* virtual time warp */
     s_time_t            warpl;            /* warp limit */
-    struct timer     warp_timer;       /* deals with warpl */
+    struct timer        warp_timer;       /* deals with warpl */
     s_time_t            warpu;            /* unwarp time requirement */
-    struct timer     unwarp_timer;     /* deals with warpu */
+    struct timer        unwarp_timer;     /* deals with warpu */
 
     struct bvt_vcpu_info vcpu_inf[MAX_VIRT_CPUS];
 };
@@ -168,6 +168,7 @@ static inline u32 calc_evt(struct vcpu *d, u32 avt)
 static int bvt_alloc_task(struct vcpu *v)
 {
     struct domain *d = v->domain;
+    struct bvt_dom_info *inf;
 
     if ( (d->sched_priv == NULL) )
     {
@@ -176,10 +177,27 @@ static int bvt_alloc_task(struct vcpu *v)
         memset(d->sched_priv, 0, sizeof(struct bvt_dom_info));
     }
 
-    v->sched_priv = &BVT_INFO(d)->vcpu_inf[v->vcpu_id];
+    inf = BVT_INFO(d);
+
+    v->sched_priv = &inf->vcpu_inf[v->vcpu_id];
 
-    BVT_INFO(d)->vcpu_inf[v->vcpu_id].inf = BVT_INFO(d);
-    BVT_INFO(d)->vcpu_inf[v->vcpu_id].vcpu = v;
+    inf->vcpu_inf[v->vcpu_id].inf  = BVT_INFO(d);
+    inf->vcpu_inf[v->vcpu_id].vcpu = v;
+
+    if ( v->vcpu_id == 0 )
+    {
+        inf->mcu_advance = MCU_ADVANCE;
+        inf->domain      = v->domain;
+        inf->warpback    = 0;
+        /* Set some default values here. */
+        inf->warp        = 0;
+        inf->warp_value  = 0;
+        inf->warpl       = MILLISECS(2000);
+        inf->warpu       = MILLISECS(1000);
+        /* Initialise the warp timers. */
+        init_timer(&inf->warp_timer, warp_timer_fn, inf, v->processor);
+        init_timer(&inf->unwarp_timer, unwarp_timer_fn, inf, v->processor);
+    }
 
     return 0;
 }
@@ -191,6 +209,7 @@ static void bvt_add_task(struct vcpu *v)
 {
     struct bvt_dom_info *inf = BVT_INFO(v->domain);
     struct bvt_vcpu_info *einf = EBVT_INFO(v);
+
     ASSERT(inf != NULL);
     ASSERT(v   != NULL);
 
@@ -203,23 +222,6 @@ static void bvt_add_task(struct vcpu *v)
         CPU_SVT(v->processor) = 0;
     }
 
-    if ( v->vcpu_id == 0 )
-    {
-        inf->mcu_advance = MCU_ADVANCE;
-        inf->domain      = v->domain;
-        inf->warpback    = 0;
-        /* Set some default values here. */
-        inf->warp        = 0;
-        inf->warp_value  = 0;
-        inf->warpl       = MILLISECS(2000);
-        inf->warpu       = MILLISECS(1000);
-        /* Initialise the warp timers. */
-        init_timer(&inf->warp_timer, warp_timer_fn, inf, v->processor);
-        init_timer(&inf->unwarp_timer, unwarp_timer_fn, inf, v->processor);
-    }
-
-    einf->vcpu = v;
-
     if ( is_idle_vcpu(v) )
     {
         einf->avt = einf->evt = ~0U;
@@ -305,8 +307,14 @@ static int bvt_set_affinity(struct vcpu *v, cpumask_t *affinity)
  */
 static void bvt_free_task(struct domain *d)
 {
-    ASSERT(d->sched_priv != NULL);
-    xfree(d->sched_priv);
+    struct bvt_dom_info *inf = BVT_INFO(d);
+
+    ASSERT(inf != NULL);
+
+    kill_timer(&inf->warp_timer);
+    kill_timer(&inf->unwarp_timer);
+
+    xfree(inf);
 }
 
 /* Control the scheduler. */
index 7d80ae78c4593d401865aa6b1fa75df96441bc91..a971d8fae1cc344af0c3a75b0af82cc23e478d94 100644 (file)
@@ -156,7 +156,7 @@ void sched_add_domain(struct vcpu *v)
 
 void sched_rem_domain(struct vcpu *v) 
 {
-    stop_timer(&v->timer);
+    kill_timer(&v->timer);
     SCHED_OP(rem_task, v);
     TRACE_2D(TRC_SCHED_DOM_REM, v->domain->domain_id, v->vcpu_id);
 }
@@ -462,7 +462,7 @@ static void s_timer_fn(void *unused)
 /* Periodic tick timer: send timer event to current domain */
 static void t_timer_fn(void *unused)
 {
-    struct vcpu  *v  = current;
+    struct vcpu  *v   = current;
     unsigned int  cpu = smp_processor_id();
 
     schedule_data[cpu].tick++;
index 336b0a15d1dd439acc2dc9ee802310ce2379d815..55f39bfa98c102cf48d70826736dc8ce885b76c3 100644 (file)
@@ -29,6 +29,7 @@
 struct timers {
     spinlock_t     lock;
     struct timer **heap;
+    struct timer  *running;
 } __cacheline_aligned;
 
 struct timers timers[NR_CPUS];
@@ -167,11 +168,11 @@ void set_timer(struct timer *timer, s_time_t expires)
     unsigned long flags;
 
     spin_lock_irqsave(&timers[cpu].lock, flags);
-    ASSERT(timer != NULL);
     if ( active_timer(timer) )
         __stop_timer(timer);
     timer->expires = expires;
-    __add_timer(timer);
+    if ( likely(!timer->killed) )
+        __add_timer(timer);
     spin_unlock_irqrestore(&timers[cpu].lock, flags);
 }
 
@@ -182,13 +183,31 @@ void stop_timer(struct timer *timer)
     unsigned long flags;
 
     spin_lock_irqsave(&timers[cpu].lock, flags);
-    ASSERT(timer != NULL);
     if ( active_timer(timer) )
         __stop_timer(timer);
     spin_unlock_irqrestore(&timers[cpu].lock, flags);
 }
 
 
+void kill_timer(struct timer *timer)
+{
+    int           cpu = timer->cpu;
+    unsigned long flags;
+
+    BUG_ON(timers[cpu].running == timer);
+
+    spin_lock_irqsave(&timers[cpu].lock, flags);
+    if ( active_timer(timer) )
+        __stop_timer(timer);
+    timer->killed = 1;
+    spin_unlock_irqrestore(&timers[cpu].lock, flags);
+
+    for_each_online_cpu ( cpu )
+        while ( timers[cpu].running == timer )
+            cpu_relax();
+}
+
+
 static void timer_softirq_action(void)
 {
     int           cpu = smp_processor_id();
@@ -208,19 +227,20 @@ static void timer_softirq_action(void)
         {
             remove_entry(heap, t);
 
+            timers[cpu].running = t;
+
             fn   = t->function;
             data = t->data;
 
-            if ( fn != NULL )
-            {
-                spin_unlock_irq(&timers[cpu].lock);
-                (*fn)(data);
-                spin_lock_irq(&timers[cpu].lock);
-            }
+            spin_unlock_irq(&timers[cpu].lock);
+            (*fn)(data);
+            spin_lock_irq(&timers[cpu].lock);
 
             /* Heap may have grown while the lock was released. */
             heap = timers[cpu].heap;
         }
+
+        timers[cpu].running = NULL;
     }
     while ( !reprogram_timer(GET_HEAP_SIZE(heap) ? heap[1]->expires : 0) );
 
index c89e98c346e5f5b377b7d13ba0dff30ac5653342..f53a7ed35f30e063e5c89adc25ee4fbeb76dd6ff 100644 (file)
@@ -22,6 +22,8 @@ struct timer {
     void         *data;
     /* Timer-heap offset. */
     unsigned int  heap_offset;
+    /* Has this timer been killed (cannot be activated)? */
+    int           killed;
 };
 
 /*
@@ -63,6 +65,13 @@ extern void set_timer(struct timer *timer, s_time_t expires);
  */
 extern void stop_timer(struct timer *timer);
 
+/*
+ * Deactivate a timer and prevent it from being re-set (future calls to
+ * set_timer will silently fail). When this function returns it is guaranteed
+ * that the timer callback handler is not running on any CPU.
+ */
+extern void kill_timer(struct timer *timer);
+
 /*
  * Initialisation. Must be called before any other timer function.
  */