# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1207924668 -3600
# Node ID 96b099ad04973e26944b8ef8196be0fd2ffdabfa
# Parent 80ba1b4270321baa58b0e8064fb472f2c2462b8d
Support tasklets in Xen as a more dynamic alternative to softirqs.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/ia64/xen/xensetup.c | 2 +
xen/arch/x86/setup.c | 2 +
xen/common/softirq.c | 74 +++++++++++++++++++++++++++++++++++++++++++
xen/include/xen/softirq.h | 61 +++++++++++++++++++++++------------
4 files changed, 118 insertions(+), 21 deletions(-)
diff -r 80ba1b427032 -r 96b099ad0497 xen/arch/ia64/xen/xensetup.c
--- a/xen/arch/ia64/xen/xensetup.c Fri Apr 11 13:19:55 2008 +0100
+++ b/xen/arch/ia64/xen/xensetup.c Fri Apr 11 15:37:48 2008 +0100
@@ -576,6 +576,8 @@ skip_move:
end_boot_allocator();
+ softirq_init();
+
late_setup_arch(&cmdline);
scheduler_init();
diff -r 80ba1b427032 -r 96b099ad0497 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c Fri Apr 11 13:19:55 2008 +0100
+++ b/xen/arch/x86/setup.c Fri Apr 11 15:37:48 2008 +0100
@@ -861,6 +861,8 @@ void __init __start_xen(unsigned long mb
early_boot = 0;
+ softirq_init();
+
early_cpu_init();
paging_init();
diff -r 80ba1b427032 -r 96b099ad0497 xen/common/softirq.c
--- a/xen/common/softirq.c Fri Apr 11 13:19:55 2008 +0100
+++ b/xen/common/softirq.c Fri Apr 11 15:37:48 2008 +0100
@@ -52,6 +52,80 @@ void open_softirq(int nr, softirq_handle
softirq_handlers[nr] = handler;
}
+static DEFINE_PER_CPU(struct tasklet *, tasklet_list);
+
+void tasklet_schedule(struct tasklet *t)
+{
+ unsigned long flags;
+
+ if ( test_and_set_bool(t->is_scheduled) )
+ return;
+
+ local_irq_save(flags);
+ t->next = this_cpu(tasklet_list);
+ this_cpu(tasklet_list) = t;
+ local_irq_restore(flags);
+
+ raise_softirq(TASKLET_SOFTIRQ);
+}
+
+static void tasklet_action(void)
+{
+ struct tasklet *list, *t;
+
+ local_irq_disable();
+ list = this_cpu(tasklet_list);
+ this_cpu(tasklet_list) = NULL;
+ local_irq_enable();
+
+ while ( (t = list) != NULL )
+ {
+ list = list->next;
+
+ BUG_ON(t->is_running);
+ t->is_running = 1;
+ smp_wmb();
+
+ BUG_ON(!t->is_scheduled);
+ t->is_scheduled = 0;
+
+ smp_mb();
+ t->func(t->data);
+ smp_mb();
+
+ t->is_running = 0;
+ }
+}
+
+void tasklet_kill(struct tasklet *t)
+{
+ /* Prevent tasklet from re-scheduling itself. */
+ while ( t->is_scheduled || test_and_set_bool(t->is_scheduled) )
+ cpu_relax();
+ smp_mb();
+
+ /* Wait for tasklet to complete. */
+ while ( t->is_running )
+ cpu_relax();
+ smp_mb();
+
+ /* Clean up and we're done. */
+ t->is_scheduled = 0;
+}
+
+void tasklet_init(
+ struct tasklet *t, void (*func)(unsigned long), unsigned long data)
+{
+ memset(t, 0, sizeof(*t));
+ t->func = func;
+ t->data = data;
+}
+
+void __init softirq_init(void)
+{
+ open_softirq(TASKLET_SOFTIRQ, tasklet_action);
+}
+
/*
* Local variables:
* mode: C
diff -r 80ba1b427032 -r 96b099ad0497 xen/include/xen/softirq.h
--- a/xen/include/xen/softirq.h Fri Apr 11 13:19:55 2008 +0100
+++ b/xen/include/xen/softirq.h Fri Apr 11 15:37:48 2008 +0100
@@ -1,24 +1,20 @@
-#ifndef __XEN_SOFTIRQ_H__
+#if !defined(__XEN_SOFTIRQ_H__) && !defined(__ASSEMBLY__)
#define __XEN_SOFTIRQ_H__
-/* Common softirqs come first in the following list. */
-#define TIMER_SOFTIRQ 0
-#define SCHEDULE_SOFTIRQ 1
-#define NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ 2
-#define KEYPRESS_SOFTIRQ 3
-#define NMI_SOFTIRQ 4
-#define PAGE_SCRUB_SOFTIRQ 5
-#define TRACE_SOFTIRQ 6
-#define RCU_SOFTIRQ 7
-#define STOPMACHINE_SOFTIRQ 8
-
-#define NR_COMMON_SOFTIRQS 9
-
-#include <asm/softirq.h>
-
-#define NR_SOFTIRQS (NR_COMMON_SOFTIRQS + NR_ARCH_SOFTIRQS)
-
-#ifndef __ASSEMBLY__
+/* Low-latency softirqs come first in the following list. */
+enum {
+ TIMER_SOFTIRQ = 0,
+ SCHEDULE_SOFTIRQ,
+ NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ,
+ KEYPRESS_SOFTIRQ,
+ NMI_SOFTIRQ,
+ PAGE_SCRUB_SOFTIRQ,
+ TRACE_SOFTIRQ,
+ RCU_SOFTIRQ,
+ STOPMACHINE_SOFTIRQ,
+ TASKLET_SOFTIRQ,
+ NR_COMMON_SOFTIRQS
+};
#include <xen/config.h>
#include <xen/lib.h>
@@ -26,11 +22,15 @@
#include <asm/bitops.h>
#include <asm/current.h>
#include <asm/hardirq.h>
+#include <asm/softirq.h>
+
+#define NR_SOFTIRQS (NR_COMMON_SOFTIRQS + NR_ARCH_SOFTIRQS)
typedef void (*softirq_handler)(void);
asmlinkage void do_softirq(void);
-extern void open_softirq(int nr, softirq_handler handler);
+void open_softirq(int nr, softirq_handler handler);
+void softirq_init(void);
static inline void cpumask_raise_softirq(cpumask_t mask, unsigned int nr)
{
@@ -56,6 +56,25 @@ static inline void raise_softirq(unsigne
set_bit(nr, &softirq_pending(smp_processor_id()));
}
-#endif /* __ASSEMBLY__ */
+/*
+ * TASKLETS -- dynamically-allocatable tasks run in softirq context
+ * on at most one CPU at a time.
+ */
+struct tasklet
+{
+ struct tasklet *next;
+ bool_t is_scheduled;
+ bool_t is_running;
+ void (*func)(unsigned long);
+ unsigned long data;
+};
+
+#define DECLARE_TASKLET(name, func, data) \
+ struct tasklet name = { NULL, 0, 0, func, data }
+
+void tasklet_schedule(struct tasklet *t);
+void tasklet_kill(struct tasklet *t);
+void tasklet_init(
+ struct tasklet *t, void (*func)(unsigned long), unsigned long data);
#endif /* __XEN_SOFTIRQ_H__ */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|