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] [xen-unstable] timer: Migrate timers from dying CPU on C

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] timer: Migrate timers from dying CPU on CPU_DYING notification.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Wed, 02 Jun 2010 23:35:11 -0700
Delivery-date: Wed, 02 Jun 2010 23:35:20 -0700
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/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1275546654 -3600
# Node ID 4ab68bf4c37e4c97e12efe7aced616ce6946578f
# Parent  5aabc6f94df5f275647d55caa24780eff0c81355
timer: Migrate timers from dying CPU on CPU_DYING notification.

Otherwise timer_lock() can race a timer's ->cpu field being updated by
migrate_timers_from_cpu().

The rest of this patch is all debug paranoia.

Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/common/timer.c |   35 ++++++++++++++++++++++++++++-------
 1 files changed, 28 insertions(+), 7 deletions(-)

diff -r 5aabc6f94df5 -r 4ab68bf4c37e xen/common/timer.c
--- a/xen/common/timer.c        Wed Jun 02 13:13:11 2010 +0100
+++ b/xen/common/timer.c        Thu Jun 03 07:30:54 2010 +0100
@@ -40,6 +40,8 @@ struct timers {
 
 static DEFINE_PER_CPU(struct timers, timers);
 
+static cpumask_t timer_valid_cpumask;
+
 DEFINE_PER_CPU(s_time_t, timer_deadline_start);
 DEFINE_PER_CPU(s_time_t, timer_deadline_end);
 
@@ -238,6 +240,7 @@ static inline void timer_lock(struct tim
     for ( ; ; )
     {
         cpu = timer->cpu;
+        ASSERT(cpu_isset(cpu, timer_valid_cpumask));
         spin_lock(&per_cpu(timers, cpu).lock);
         if ( likely(timer->cpu == cpu) )
             break;
@@ -329,6 +332,9 @@ void migrate_timer(struct timer *timer, 
     {
         if ( (old_cpu = timer->cpu) == new_cpu )
             return;
+
+        ASSERT(cpu_isset(old_cpu, timer_valid_cpumask));
+        ASSERT(cpu_isset(new_cpu, timer_valid_cpumask));
 
         if ( old_cpu < new_cpu )
         {
@@ -553,23 +559,27 @@ static struct keyhandler dump_timerq_key
     .desc = "dump timer queues"
 };
 
-static void migrate_timers_from_cpu(unsigned int cpu)
+static unsigned int migrate_timers_from_cpu(unsigned int cpu)
 {
     struct timers *ts;
     struct timer *t;
+    bool_t notify = 0;
+    unsigned int nr_migrated = 0;
+    unsigned long flags;
 
     ASSERT((cpu != 0) && cpu_online(0));
 
     ts = &per_cpu(timers, cpu);
 
-    spin_lock_irq(&per_cpu(timers, 0).lock);
+    spin_lock_irqsave(&per_cpu(timers, 0).lock, flags);
     spin_lock(&ts->lock);
 
     while ( (t = GET_HEAP_SIZE(ts->heap) ? ts->heap[1] : ts->list) != NULL )
     {
         remove_entry(t);
         t->cpu = 0;
-        add_entry(t);
+        notify |= add_entry(t);
+        nr_migrated++;
     }
 
     while ( !list_empty(&ts->inactive) )
@@ -578,12 +588,16 @@ static void migrate_timers_from_cpu(unsi
         list_del(&t->inactive);
         t->cpu = 0;
         list_add(&t->inactive, &per_cpu(timers, 0).inactive);
+        nr_migrated++;
     }
 
     spin_unlock(&ts->lock);
-    spin_unlock_irq(&per_cpu(timers, 0).lock);
-
-    cpu_raise_softirq(0, TIMER_SOFTIRQ);
+    spin_unlock_irqrestore(&per_cpu(timers, 0).lock, flags);
+
+    if ( notify )
+        cpu_raise_softirq(0, TIMER_SOFTIRQ);
+
+    return nr_migrated;
 }
 
 static struct timer *dummy_heap;
@@ -600,10 +614,17 @@ static int cpu_callback(
         INIT_LIST_HEAD(&ts->inactive);
         spin_lock_init(&ts->lock);
         ts->heap = &dummy_heap;
+        cpu_set(cpu, timer_valid_cpumask);
+        break;
+    case CPU_DYING:
+        cpu_clear(cpu, timer_valid_cpumask);
+        migrate_timers_from_cpu(cpu);
         break;
     case CPU_UP_CANCELED:
     case CPU_DEAD:
-        migrate_timers_from_cpu(cpu);
+        cpu_clear(cpu, timer_valid_cpumask);
+        if ( migrate_timers_from_cpu(cpu) )
+            BUG();
         break;
     default:
         break;

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] timer: Migrate timers from dying CPU on CPU_DYING notification., Xen patchbot-unstable <=