WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

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

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Fix Xen timer interface to allow migration of timers
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 08 Feb 2006 18:36:12 +0000
Delivery-date: Wed, 08 Feb 2006 18:48:23 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Fix Xen timer interface to allow migration of timers, Xen patchbot -unstable <=