[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Fix Xen timer interface to allow migration of timers



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 974ed9f7364198b2f3be194847e3b0538f88d5d8
# Parent  b246f429f683cce73bf7486c37bf6842983fa49f
Fix Xen timer interface to allow migration of timers
among CPUs (using new migrate_timer() call). Fix the
locking protocol in light of this addition.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r b246f429f683 -r 974ed9f73641 xen/common/timer.c
--- a/xen/common/timer.c        Wed Feb  8 16:26:20 2006
+++ b/xen/common/timer.c        Wed Feb  8 16:27:32 2006
@@ -161,46 +161,122 @@
         cpu_raise_softirq(cpu, TIMER_SOFTIRQ);
 }
 
+static inline void timer_lock(struct timer *timer)
+{
+    unsigned int cpu;
+
+    for ( ; ; )
+    {
+        cpu = timer->cpu;
+        spin_lock(&timers[cpu].lock);
+        if ( likely(timer->cpu == cpu) )
+            break;
+        spin_unlock(&timers[cpu].lock);
+    }
+}
+
+#define timer_lock_irq(t) \
+    do { local_irq_disable(); timer_lock(t); } while ( 0 )
+#define timer_lock_irqsave(t, flags) \
+    do { local_irq_save(flags); timer_lock(t); } while ( 0 )
+
+static inline void timer_unlock(struct timer *timer)
+{
+        spin_unlock(&timers[timer->cpu].lock);
+}
+
+#define timer_unlock_irq(t) \
+    do { timer_unlock(t); local_irq_enable(); } while ( 0 )
+#define timer_unlock_irqrestore(t, flags) \
+    do { timer_unlock(t); local_irq_restore(flags); } while ( 0 )
+
 
 void set_timer(struct timer *timer, s_time_t expires)
 {
-    int           cpu = timer->cpu;
     unsigned long flags;
 
-    spin_lock_irqsave(&timers[cpu].lock, flags);
+    timer_lock_irqsave(timer, flags);
+
     if ( active_timer(timer) )
         __stop_timer(timer);
+
     timer->expires = expires;
+
     if ( likely(!timer->killed) )
         __add_timer(timer);
-    spin_unlock_irqrestore(&timers[cpu].lock, flags);
+
+    timer_unlock_irqrestore(timer, flags);
 }
 
 
 void stop_timer(struct timer *timer)
 {
-    int           cpu = timer->cpu;
     unsigned long flags;
 
-    spin_lock_irqsave(&timers[cpu].lock, flags);
+    timer_lock_irqsave(timer, flags);
+
     if ( active_timer(timer) )
         __stop_timer(timer);
-    spin_unlock_irqrestore(&timers[cpu].lock, flags);
+
+    timer_unlock_irqrestore(timer, flags);
+}
+
+
+void migrate_timer(struct timer *timer, unsigned int new_cpu)
+{
+    int           old_cpu;
+    unsigned long flags;
+
+    for ( ; ; )
+    {
+        if ( (old_cpu = timer->cpu) == new_cpu )
+            return;
+
+        if ( old_cpu < new_cpu )
+        {
+            spin_lock_irqsave(&timers[old_cpu].lock, flags);
+            spin_lock(&timers[new_cpu].lock);
+        }
+        else
+        {
+            spin_lock_irqsave(&timers[new_cpu].lock, flags);
+            spin_lock(&timers[old_cpu].lock);
+        }
+
+        if ( likely(timer->cpu == old_cpu) )
+             break;
+
+        spin_unlock(&timers[old_cpu].lock);
+        spin_unlock_irqrestore(&timers[new_cpu].lock, flags);
+    }
+
+    if ( active_timer(timer) )
+        __stop_timer(timer);
+
+    timer->cpu = new_cpu;
+
+    if ( likely(!timer->killed) )
+        __add_timer(timer);
+
+    spin_unlock(&timers[old_cpu].lock);
+    spin_unlock_irqrestore(&timers[new_cpu].lock, flags);
 }
 
 
 void kill_timer(struct timer *timer)
 {
-    int           cpu = timer->cpu;
+    int           cpu;
     unsigned long flags;
 
-    BUG_ON(timers[cpu].running == timer);
-
-    spin_lock_irqsave(&timers[cpu].lock, flags);
+    BUG_ON(timers[smp_processor_id()].running == timer);
+
+    timer_lock_irqsave(timer, flags);
+
     if ( active_timer(timer) )
         __stop_timer(timer);
     timer->killed = 1;
-    spin_unlock_irqrestore(&timers[cpu].lock, flags);
+
+    timer_unlock_irqrestore(timer, flags);
 
     for_each_online_cpu ( cpu )
         while ( timers[cpu].running == timer )
diff -r b246f429f683 -r 974ed9f73641 xen/include/xen/timer.h
--- a/xen/include/xen/timer.h   Wed Feb  8 16:26:20 2006
+++ b/xen/include/xen/timer.h   Wed Feb  8 16:27:32 2006
@@ -66,6 +66,12 @@
 extern void stop_timer(struct timer *timer);
 
 /*
+ * Migrate a timer to a different CPU. The timer must have been previously
+ * initialised by init_timer(). The timer may be active.
+ */
+extern void migrate_timer(struct timer *timer, unsigned int new_cpu);
+
+/*
  * 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.

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.