--- kernel/softirq.c.orig 2004-03-11 03:55:24.000000000 +0100 +++ kernel/softirq.c 2004-03-31 18:15:26.000000000 +0200 @@ -69,7 +69,13 @@ */ #define MAX_SOFTIRQ_RESTART 10 -asmlinkage void do_softirq(void) + +/* Use the fastroute stats. */ + +#include +DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat); + +asmlinkage void do_softirq(int from) { int max_restart = MAX_SOFTIRQ_RESTART; __u32 pending; @@ -84,9 +90,44 @@ if (pending) { struct softirq_action *h; + struct task_struct *tsk = __get_cpu_var(ksoftirqd); local_bh_disable(); +#if 0 + /* Avoid softirq's from DoS'ing user apps incl. RCU's etc */ + + if (unlikely(from != SIRQ_FROM_KSOFTIRQD && + tsk && + sched_clock() - tsk->timestamp > + (unsigned long long) 2*1000000000 && + !(current->state & (TASK_DEAD | TASK_ZOMBIE)))) { + + set_tsk_need_resched(current); + local_irq_disable(); + goto done; + } +#endif + restart: + switch (from) { + + case SIRQ_FROM_BH: + __get_cpu_var(netdev_rx_stat).fastroute_hit++; + break; + + case SIRQ_FROM_KSOFTIRQD: + __get_cpu_var(netdev_rx_stat).fastroute_success++; + break; + + case SIRQ_FROM_IRQEXIT: + __get_cpu_var(netdev_rx_stat).fastroute_defer++; + break; + + + default: + __get_cpu_var(netdev_rx_stat).fastroute_deferred_out++; + + } /* Reset the pending bitmask before enabling irqs */ local_softirq_pending() = 0; @@ -106,6 +147,7 @@ pending = local_softirq_pending(); if (pending && --max_restart) goto restart; + done: if (pending) wakeup_softirqd(); __local_bh_enable(); @@ -122,7 +164,7 @@ WARN_ON(irqs_disabled()); if (unlikely(!in_interrupt() && local_softirq_pending())) - invoke_softirq(); + invoke_softirq(SIRQ_FROM_BH); preempt_check_resched(); } EXPORT_SYMBOL(local_bh_enable); @@ -324,7 +366,7 @@ __set_current_state(TASK_RUNNING); while (local_softirq_pending()) { - do_softirq(); + do_softirq(SIRQ_FROM_KSOFTIRQD); cond_resched(); } --- include/linux/netdevice.h~ 2004-03-11 03:55:44.000000000 +0100 +++ include/linux/netdevice.h 2004-03-31 12:24:57.000000000 +0200 @@ -669,7 +669,7 @@ { int err = netif_rx(skb); if (softirq_pending(smp_processor_id())) - do_softirq(); + do_softirq(SIRQ_FROM_NETIF_RX_NI); return err; } --- include/linux/interrupt.h.orig 2004-03-31 18:24:03.000000000 +0200 +++ include/linux/interrupt.h 2004-03-31 18:19:28.000000000 +0200 @@ -92,7 +92,17 @@ void *data; }; -asmlinkage void do_softirq(void); +/* Softirq originator */ +enum +{ + SIRQ_FROM_KSOFTIRQD=0, + SIRQ_FROM_IRQEXIT, + SIRQ_FROM_BH, + SIRQ_FROM_NETIF_RX_NI, + SIRQ_FROM_PKTGEN +}; + +asmlinkage void do_softirq(int from); extern void open_softirq(int nr, void (*action)(struct softirq_action*), void *data); extern void softirq_init(void); #define __raise_softirq_irqoff(nr) do { local_softirq_pending() |= 1UL << (nr); } while (0) @@ -100,7 +110,7 @@ extern void FASTCALL(raise_softirq(unsigned int nr)); #ifndef invoke_softirq -#define invoke_softirq() do_softirq() +#define invoke_softirq(from) do_softirq(from) #endif --- include/asm-i386/hardirq.h.orig 2004-03-11 03:55:37.000000000 +0100 +++ include/asm-i386/hardirq.h 2004-03-31 18:27:17.000000000 +0200 @@ -88,7 +88,7 @@ do { \ preempt_count() -= IRQ_EXIT_OFFSET; \ if (!in_interrupt() && softirq_pending(smp_processor_id())) \ - do_softirq(); \ + do_softirq(SIRQ_FROM_IRQEXIT); \ preempt_enable_no_resched(); \ } while (0) --- net/core/pktgen.c~ 2004-03-11 03:55:36.000000000 +0100 +++ net/core/pktgen.c 2004-03-31 12:24:57.000000000 +0200 @@ -710,7 +710,7 @@ if (need_resched()) schedule(); else - do_softirq(); + do_softirq(SIRQ_FROM_PKTGEN); } while (netif_queue_stopped(odev)); idle = cycles() - idle_start; info->idle_acc += idle;