ia64/xen-unstable

changeset 17444:96b099ad0497

Support tasklets in Xen as a more dynamic alternative to softirqs.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Apr 11 15:37:48 2008 +0100 (2008-04-11)
parents 80ba1b427032
children d2010614d9f1
files xen/arch/ia64/xen/xensetup.c xen/arch/x86/setup.c xen/common/softirq.c xen/include/xen/softirq.h
line diff
     1.1 --- a/xen/arch/ia64/xen/xensetup.c	Fri Apr 11 13:19:55 2008 +0100
     1.2 +++ b/xen/arch/ia64/xen/xensetup.c	Fri Apr 11 15:37:48 2008 +0100
     1.3 @@ -576,6 +576,8 @@ skip_move:
     1.4  
     1.5      end_boot_allocator();
     1.6  
     1.7 +    softirq_init();
     1.8 +
     1.9      late_setup_arch(&cmdline);
    1.10  
    1.11      scheduler_init();
     2.1 --- a/xen/arch/x86/setup.c	Fri Apr 11 13:19:55 2008 +0100
     2.2 +++ b/xen/arch/x86/setup.c	Fri Apr 11 15:37:48 2008 +0100
     2.3 @@ -861,6 +861,8 @@ void __init __start_xen(unsigned long mb
     2.4  
     2.5      early_boot = 0;
     2.6  
     2.7 +    softirq_init();
     2.8 +
     2.9      early_cpu_init();
    2.10  
    2.11      paging_init();
     3.1 --- a/xen/common/softirq.c	Fri Apr 11 13:19:55 2008 +0100
     3.2 +++ b/xen/common/softirq.c	Fri Apr 11 15:37:48 2008 +0100
     3.3 @@ -52,6 +52,80 @@ void open_softirq(int nr, softirq_handle
     3.4      softirq_handlers[nr] = handler;
     3.5  }
     3.6  
     3.7 +static DEFINE_PER_CPU(struct tasklet *, tasklet_list);
     3.8 +
     3.9 +void tasklet_schedule(struct tasklet *t)
    3.10 +{
    3.11 +    unsigned long flags;
    3.12 +
    3.13 +    if ( test_and_set_bool(t->is_scheduled) )
    3.14 +        return;
    3.15 +
    3.16 +    local_irq_save(flags);
    3.17 +    t->next = this_cpu(tasklet_list);
    3.18 +    this_cpu(tasklet_list) = t;
    3.19 +    local_irq_restore(flags);
    3.20 +
    3.21 +    raise_softirq(TASKLET_SOFTIRQ);
    3.22 +}
    3.23 +
    3.24 +static void tasklet_action(void)
    3.25 +{
    3.26 +    struct tasklet *list, *t;
    3.27 +
    3.28 +    local_irq_disable();
    3.29 +    list = this_cpu(tasklet_list);
    3.30 +    this_cpu(tasklet_list) = NULL;
    3.31 +    local_irq_enable();
    3.32 +
    3.33 +    while ( (t = list) != NULL )
    3.34 +    {
    3.35 +        list = list->next;
    3.36 +
    3.37 +        BUG_ON(t->is_running);
    3.38 +        t->is_running = 1;
    3.39 +        smp_wmb();
    3.40 +
    3.41 +        BUG_ON(!t->is_scheduled);
    3.42 +        t->is_scheduled = 0;
    3.43 +
    3.44 +        smp_mb();
    3.45 +        t->func(t->data);
    3.46 +        smp_mb();
    3.47 +
    3.48 +        t->is_running = 0;
    3.49 +    }
    3.50 +}
    3.51 +
    3.52 +void tasklet_kill(struct tasklet *t)
    3.53 +{
    3.54 +    /* Prevent tasklet from re-scheduling itself. */
    3.55 +    while ( t->is_scheduled || test_and_set_bool(t->is_scheduled) )
    3.56 +        cpu_relax();
    3.57 +    smp_mb();
    3.58 +
    3.59 +    /* Wait for tasklet to complete. */
    3.60 +    while ( t->is_running )
    3.61 +        cpu_relax();
    3.62 +    smp_mb();
    3.63 +
    3.64 +    /* Clean up and we're done. */
    3.65 +    t->is_scheduled = 0;
    3.66 +}
    3.67 +
    3.68 +void tasklet_init(
    3.69 +    struct tasklet *t, void (*func)(unsigned long), unsigned long data)
    3.70 +{
    3.71 +    memset(t, 0, sizeof(*t));
    3.72 +    t->func = func;
    3.73 +    t->data = data;
    3.74 +}
    3.75 +
    3.76 +void __init softirq_init(void)
    3.77 +{
    3.78 +    open_softirq(TASKLET_SOFTIRQ, tasklet_action);
    3.79 +}
    3.80 +
    3.81  /*
    3.82   * Local variables:
    3.83   * mode: C
     4.1 --- a/xen/include/xen/softirq.h	Fri Apr 11 13:19:55 2008 +0100
     4.2 +++ b/xen/include/xen/softirq.h	Fri Apr 11 15:37:48 2008 +0100
     4.3 @@ -1,24 +1,20 @@
     4.4 -#ifndef __XEN_SOFTIRQ_H__
     4.5 +#if !defined(__XEN_SOFTIRQ_H__) && !defined(__ASSEMBLY__)
     4.6  #define __XEN_SOFTIRQ_H__
     4.7  
     4.8 -/* Common softirqs come first in the following list. */
     4.9 -#define TIMER_SOFTIRQ                     0
    4.10 -#define SCHEDULE_SOFTIRQ                  1
    4.11 -#define NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ 2
    4.12 -#define KEYPRESS_SOFTIRQ                  3
    4.13 -#define NMI_SOFTIRQ                       4
    4.14 -#define PAGE_SCRUB_SOFTIRQ                5
    4.15 -#define TRACE_SOFTIRQ                     6
    4.16 -#define RCU_SOFTIRQ                       7
    4.17 -#define STOPMACHINE_SOFTIRQ               8
    4.18 -
    4.19 -#define NR_COMMON_SOFTIRQS                9
    4.20 -
    4.21 -#include <asm/softirq.h>
    4.22 -
    4.23 -#define NR_SOFTIRQS (NR_COMMON_SOFTIRQS + NR_ARCH_SOFTIRQS)
    4.24 -
    4.25 -#ifndef __ASSEMBLY__
    4.26 +/* Low-latency softirqs come first in the following list. */
    4.27 +enum {
    4.28 +    TIMER_SOFTIRQ = 0,
    4.29 +    SCHEDULE_SOFTIRQ,
    4.30 +    NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ,
    4.31 +    KEYPRESS_SOFTIRQ,
    4.32 +    NMI_SOFTIRQ,
    4.33 +    PAGE_SCRUB_SOFTIRQ,
    4.34 +    TRACE_SOFTIRQ,
    4.35 +    RCU_SOFTIRQ,
    4.36 +    STOPMACHINE_SOFTIRQ,
    4.37 +    TASKLET_SOFTIRQ,
    4.38 +    NR_COMMON_SOFTIRQS
    4.39 +};
    4.40  
    4.41  #include <xen/config.h>
    4.42  #include <xen/lib.h>
    4.43 @@ -26,11 +22,15 @@
    4.44  #include <asm/bitops.h>
    4.45  #include <asm/current.h>
    4.46  #include <asm/hardirq.h>
    4.47 +#include <asm/softirq.h>
    4.48 +
    4.49 +#define NR_SOFTIRQS (NR_COMMON_SOFTIRQS + NR_ARCH_SOFTIRQS)
    4.50  
    4.51  typedef void (*softirq_handler)(void);
    4.52  
    4.53  asmlinkage void do_softirq(void);
    4.54 -extern void open_softirq(int nr, softirq_handler handler);
    4.55 +void open_softirq(int nr, softirq_handler handler);
    4.56 +void softirq_init(void);
    4.57  
    4.58  static inline void cpumask_raise_softirq(cpumask_t mask, unsigned int nr)
    4.59  {
    4.60 @@ -56,6 +56,25 @@ static inline void raise_softirq(unsigne
    4.61      set_bit(nr, &softirq_pending(smp_processor_id()));
    4.62  }
    4.63  
    4.64 -#endif /* __ASSEMBLY__ */
    4.65 +/*
    4.66 + * TASKLETS -- dynamically-allocatable tasks run in softirq context
    4.67 + * on at most one CPU at a time.
    4.68 + */
    4.69 +struct tasklet
    4.70 +{
    4.71 +    struct tasklet *next;
    4.72 +    bool_t is_scheduled;
    4.73 +    bool_t is_running;
    4.74 +    void (*func)(unsigned long);
    4.75 +    unsigned long data;
    4.76 +};
    4.77 +
    4.78 +#define DECLARE_TASKLET(name, func, data) \
    4.79 +    struct tasklet name = { NULL, 0, 0, func, data }
    4.80 +
    4.81 +void tasklet_schedule(struct tasklet *t);
    4.82 +void tasklet_kill(struct tasklet *t);
    4.83 +void tasklet_init(
    4.84 +    struct tasklet *t, void (*func)(unsigned long), unsigned long data);
    4.85  
    4.86  #endif /* __XEN_SOFTIRQ_H__ */