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] Per-cpu tasklet lists.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] Per-cpu tasklet lists.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 15 Apr 2010 01:35:11 -0700
Delivery-date: Thu, 15 Apr 2010 01:37:51 -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 1271238269 -3600
# Node ID 5057604eeefcb6479cc97c092a2399a115fae879
# Parent  c02cc832cb2d88c383d33c1ba50c381fae703308
Per-cpu tasklet lists.

Signed-off-by: Juergen Gross <juergen.gross@xxxxxxxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 xen/arch/x86/smpboot.c    |    1 
 xen/common/softirq.c      |   95 ++++++++++++++++++++++++++++++++--------------
 xen/include/xen/softirq.h |    6 +-
 3 files changed, 73 insertions(+), 29 deletions(-)

diff -r c02cc832cb2d -r 5057604eeefc xen/arch/x86/smpboot.c
--- a/xen/arch/x86/smpboot.c    Tue Apr 13 18:19:33 2010 +0100
+++ b/xen/arch/x86/smpboot.c    Wed Apr 14 10:44:29 2010 +0100
@@ -1374,6 +1374,7 @@ int cpu_down(unsigned int cpu)
 
        BUG_ON(cpu_online(cpu));
 
+       migrate_tasklets_from_cpu(cpu);
        cpu_mcheck_distribute_cmci();
 
 out:
diff -r c02cc832cb2d -r 5057604eeefc xen/common/softirq.c
--- a/xen/common/softirq.c      Tue Apr 13 18:19:33 2010 +0100
+++ b/xen/common/softirq.c      Wed Apr 14 10:44:29 2010 +0100
@@ -78,7 +78,8 @@ void cpumask_raise_softirq(cpumask_t mas
 
 void cpu_raise_softirq(unsigned int cpu, unsigned int nr)
 {
-    if ( !test_and_set_bit(nr, &softirq_pending(cpu)) )
+    if ( !test_and_set_bit(nr, &softirq_pending(cpu))
+         && (cpu != smp_processor_id()) )
         smp_send_event_check_cpu(cpu);
 }
 
@@ -87,46 +88,54 @@ void raise_softirq(unsigned int nr)
     set_bit(nr, &softirq_pending(smp_processor_id()));
 }
 
-static LIST_HEAD(tasklet_list);
+static bool_t tasklets_initialised;
+static DEFINE_PER_CPU(struct list_head, tasklet_list);
 static DEFINE_SPINLOCK(tasklet_lock);
 
+void tasklet_schedule_on_cpu(struct tasklet *t, unsigned int cpu)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&tasklet_lock, flags);
+
+    if ( tasklets_initialised && !t->is_dead )
+    {
+        t->scheduled_on = cpu;
+        if ( !t->is_running )
+        {
+            list_del(&t->list);
+            list_add_tail(&t->list, &per_cpu(tasklet_list, cpu));
+            cpu_raise_softirq(cpu, TASKLET_SOFTIRQ);
+        }
+    }
+
+    spin_unlock_irqrestore(&tasklet_lock, flags);
+}
+
 void tasklet_schedule(struct tasklet *t)
 {
-    unsigned long flags;
-
-    spin_lock_irqsave(&tasklet_lock, flags);
-
-    if ( !t->is_dead )
-    {
-        if ( !t->is_scheduled && !t->is_running )
-        {
-            BUG_ON(!list_empty(&t->list));
-            list_add_tail(&t->list, &tasklet_list);
-        }
-        t->is_scheduled = 1;
-        raise_softirq(TASKLET_SOFTIRQ);
-    }
-
-    spin_unlock_irqrestore(&tasklet_lock, flags);
+    tasklet_schedule_on_cpu(t, smp_processor_id());
 }
 
 static void tasklet_action(void)
 {
+    unsigned int cpu = smp_processor_id();
+    struct list_head *list = &per_cpu(tasklet_list, cpu);
     struct tasklet *t;
 
     spin_lock_irq(&tasklet_lock);
 
-    if ( list_empty(&tasklet_list) )
+    if ( list_empty(list) )
     {
         spin_unlock_irq(&tasklet_lock);
         return;
     }
 
-    t = list_entry(tasklet_list.next, struct tasklet, list);
+    t = list_entry(list->next, struct tasklet, list);
     list_del_init(&t->list);
 
-    BUG_ON(t->is_dead || t->is_running || !t->is_scheduled);
-    t->is_scheduled = 0;
+    BUG_ON(t->is_dead || t->is_running || (t->scheduled_on != cpu));
+    t->scheduled_on = -1;
     t->is_running = 1;
 
     spin_unlock_irq(&tasklet_lock);
@@ -135,17 +144,19 @@ static void tasklet_action(void)
 
     t->is_running = 0;
 
-    if ( t->is_scheduled )
+    if ( t->scheduled_on >= 0 )
     {
         BUG_ON(t->is_dead || !list_empty(&t->list));
-        list_add_tail(&t->list, &tasklet_list);
+        list_add_tail(&t->list, &per_cpu(tasklet_list, t->scheduled_on));
+        if ( t->scheduled_on != cpu )
+            cpu_raise_softirq(cpu, TASKLET_SOFTIRQ);
     }
 
     /*
      * If there is more work to do then reschedule. We don't grab more work
      * immediately as we want to allow other softirq work to happen first.
      */
-    if ( !list_empty(&tasklet_list) )
+    if ( !list_empty(list) )
         raise_softirq(TASKLET_SOFTIRQ);
 
     spin_unlock_irq(&tasklet_lock);
@@ -159,10 +170,10 @@ void tasklet_kill(struct tasklet *t)
 
     if ( !list_empty(&t->list) )
     {
-        BUG_ON(t->is_dead || t->is_running || !t->is_scheduled);
+        BUG_ON(t->is_dead || t->is_running || (t->scheduled_on < 0));
         list_del_init(&t->list);
     }
-    t->is_scheduled = 0;
+    t->scheduled_on = -1;
     t->is_dead = 1;
 
     while ( t->is_running )
@@ -175,18 +186,48 @@ void tasklet_kill(struct tasklet *t)
     spin_unlock_irqrestore(&tasklet_lock, flags);
 }
 
+void migrate_tasklets_from_cpu(unsigned int cpu)
+{
+    struct list_head *list = &per_cpu(tasklet_list, cpu);
+    unsigned long flags;
+    struct tasklet *t;
+
+    spin_lock_irqsave(&tasklet_lock, flags);
+
+    while ( !list_empty(list) )
+    {
+        t = list_entry(list->next, struct tasklet, list);
+        BUG_ON(t->scheduled_on != cpu);
+        t->scheduled_on = smp_processor_id();
+        list_del(&t->list);
+        list_add_tail(&t->list, &this_cpu(tasklet_list));
+    }
+
+    raise_softirq(TASKLET_SOFTIRQ);
+
+    spin_unlock_irqrestore(&tasklet_lock, flags);
+}
+
 void tasklet_init(
     struct tasklet *t, void (*func)(unsigned long), unsigned long data)
 {
     memset(t, 0, sizeof(*t));
     INIT_LIST_HEAD(&t->list);
+    t->scheduled_on = -1;
     t->func = func;
     t->data = data;
 }
 
 void __init softirq_init(void)
 {
+    unsigned int cpu;
+
+    for_each_possible_cpu ( cpu )
+        INIT_LIST_HEAD(&per_cpu(tasklet_list, cpu));
+
     open_softirq(TASKLET_SOFTIRQ, tasklet_action);
+
+    tasklets_initialised = 1;
 }
 
 /*
diff -r c02cc832cb2d -r 5057604eeefc xen/include/xen/softirq.h
--- a/xen/include/xen/softirq.h Tue Apr 13 18:19:33 2010 +0100
+++ b/xen/include/xen/softirq.h Wed Apr 14 10:44:29 2010 +0100
@@ -47,7 +47,7 @@ struct tasklet
 struct tasklet
 {
     struct list_head list;
-    bool_t is_scheduled;
+    int scheduled_on;
     bool_t is_running;
     bool_t is_dead;
     void (*func)(unsigned long);
@@ -55,10 +55,12 @@ struct tasklet
 };
 
 #define DECLARE_TASKLET(name, func, data) \
-    struct tasklet name = { LIST_HEAD_INIT(name.list), 0, 0, 0, func, data }
+    struct tasklet name = { LIST_HEAD_INIT(name.list), -1, 0, 0, func, data }
 
+void tasklet_schedule_on_cpu(struct tasklet *t, unsigned int cpu);
 void tasklet_schedule(struct tasklet *t);
 void tasklet_kill(struct tasklet *t);
+void migrate_tasklets_from_cpu(unsigned int cpu);
 void tasklet_init(
     struct tasklet *t, void (*func)(unsigned long), unsigned long data);
 

_______________________________________________
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] Per-cpu tasklet lists., Xen patchbot-unstable <=