aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-04-19 10:06:42 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-04-19 10:06:42 +0100
commit197965150c69bde1d38ead5e8c7eb7bfa211d498 (patch)
tree859611772155be5af5284c45efdad446b6edd8a3 /xen/common
parentf770264fe1f91d685499179e0e9c339fa0aaa6a8 (diff)
downloadxen-197965150c69bde1d38ead5e8c7eb7bfa211d498.tar.gz
xen-197965150c69bde1d38ead5e8c7eb7bfa211d498.tar.bz2
xen-197965150c69bde1d38ead5e8c7eb7bfa211d498.zip
Move tasklet implementation into its own source files.
This is preparation for implementing tasklets in vcpu context rather than softirq context. There is no change to the implementation of tasklets in this patch. Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen/common')
-rw-r--r--xen/common/Makefile1
-rw-r--r--xen/common/domain.c1
-rw-r--r--xen/common/keyhandler.c2
-rw-r--r--xen/common/softirq.c138
-rw-r--r--xen/common/tasklet.c170
-rw-r--r--xen/common/trace.c2
6 files changed, 174 insertions, 140 deletions
diff --git a/xen/common/Makefile b/xen/common/Makefile
index baa6b5872b..c36d0f351d 100644
--- a/xen/common/Makefile
+++ b/xen/common/Makefile
@@ -23,6 +23,7 @@ obj-y += stop_machine.o
obj-y += string.o
obj-y += symbols.o
obj-y += sysctl.o
+obj-y += tasklet.o
obj-y += time.o
obj-y += timer.o
obj-y += trace.o
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 808d250930..f67445c77e 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -17,6 +17,7 @@
#include <xen/time.h>
#include <xen/console.h>
#include <xen/softirq.h>
+#include <xen/tasklet.h>
#include <xen/domain_page.h>
#include <xen/rangeset.h>
#include <xen/guest_access.h>
diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c
index e3e64a1953..611724a645 100644
--- a/xen/common/keyhandler.c
+++ b/xen/common/keyhandler.c
@@ -9,7 +9,7 @@
#include <xen/console.h>
#include <xen/serial.h>
#include <xen/sched.h>
-#include <xen/softirq.h>
+#include <xen/tasklet.h>
#include <xen/domain.h>
#include <xen/rangeset.h>
#include <xen/compat.h>
diff --git a/xen/common/softirq.c b/xen/common/softirq.c
index e90b71ed2b..fac59818ac 100644
--- a/xen/common/softirq.c
+++ b/xen/common/softirq.c
@@ -88,146 +88,8 @@ void raise_softirq(unsigned int nr)
set_bit(nr, &softirq_pending(smp_processor_id()));
}
-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)
-{
- 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(list) )
- {
- spin_unlock_irq(&tasklet_lock);
- return;
- }
-
- t = list_entry(list->next, struct tasklet, list);
- list_del_init(&t->list);
-
- 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);
- t->func(t->data);
- spin_lock_irq(&tasklet_lock);
-
- t->is_running = 0;
-
- if ( t->scheduled_on >= 0 )
- {
- BUG_ON(t->is_dead || !list_empty(&t->list));
- list_add_tail(&t->list, &per_cpu(tasklet_list, t->scheduled_on));
- if ( t->scheduled_on != cpu )
- cpu_raise_softirq(t->scheduled_on, 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(list) )
- raise_softirq(TASKLET_SOFTIRQ);
-
- spin_unlock_irq(&tasklet_lock);
-}
-
-void tasklet_kill(struct tasklet *t)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&tasklet_lock, flags);
-
- if ( !list_empty(&t->list) )
- {
- BUG_ON(t->is_dead || t->is_running || (t->scheduled_on < 0));
- list_del_init(&t->list);
- }
- t->scheduled_on = -1;
- t->is_dead = 1;
-
- while ( t->is_running )
- {
- spin_unlock_irqrestore(&tasklet_lock, flags);
- cpu_relax();
- spin_lock_irqsave(&tasklet_lock, flags);
- }
-
- 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 --git a/xen/common/tasklet.c b/xen/common/tasklet.c
new file mode 100644
index 0000000000..c7d692bfbc
--- /dev/null
+++ b/xen/common/tasklet.c
@@ -0,0 +1,170 @@
+/******************************************************************************
+ * tasklet.c
+ *
+ * Dynamically-allocatable tasks run in softirq context on at most one CPU at
+ * a time.
+ *
+ * Copyright (c) 2010, Citrix Systems, Inc.
+ * Copyright (c) 1992, Linus Torvalds
+ *
+ * Authors:
+ * Keir Fraser <keir.fraser@citrix.com>
+ */
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/sched.h>
+#include <xen/softirq.h>
+#include <xen/tasklet.h>
+
+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)
+{
+ 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(list) )
+ {
+ spin_unlock_irq(&tasklet_lock);
+ return;
+ }
+
+ t = list_entry(list->next, struct tasklet, list);
+ list_del_init(&t->list);
+
+ 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);
+ t->func(t->data);
+ spin_lock_irq(&tasklet_lock);
+
+ t->is_running = 0;
+
+ if ( t->scheduled_on >= 0 )
+ {
+ BUG_ON(t->is_dead || !list_empty(&t->list));
+ list_add_tail(&t->list, &per_cpu(tasklet_list, t->scheduled_on));
+ if ( t->scheduled_on != cpu )
+ cpu_raise_softirq(t->scheduled_on, 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(list) )
+ raise_softirq(TASKLET_SOFTIRQ);
+
+ spin_unlock_irq(&tasklet_lock);
+}
+
+void tasklet_kill(struct tasklet *t)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&tasklet_lock, flags);
+
+ if ( !list_empty(&t->list) )
+ {
+ BUG_ON(t->is_dead || t->is_running || (t->scheduled_on < 0));
+ list_del_init(&t->list);
+ }
+ t->scheduled_on = -1;
+ t->is_dead = 1;
+
+ while ( t->is_running )
+ {
+ spin_unlock_irqrestore(&tasklet_lock, flags);
+ cpu_relax();
+ spin_lock_irqsave(&tasklet_lock, flags);
+ }
+
+ 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 tasklet_subsys_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;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/common/trace.c b/xen/common/trace.c
index cd1f0fb7f6..110f3b8c7d 100644
--- a/xen/common/trace.c
+++ b/xen/common/trace.c
@@ -25,7 +25,7 @@
#include <xen/trace.h>
#include <xen/errno.h>
#include <xen/event.h>
-#include <xen/softirq.h>
+#include <xen/tasklet.h>
#include <xen/init.h>
#include <xen/mm.h>
#include <xen/percpu.h>