--- kernel/softirq.c.orig 2004-03-11 03:55:24.000000000 +0100 +++ kernel/softirq.c 2004-04-05 12:52:40.000000000 +0200 @@ -58,6 +58,14 @@ wake_up_process(tsk); } +static inline int can_run_ksoftirqd(void) +{ + /* Interrupts are disabled: no need to stop preemption */ + struct task_struct *tsk = __get_cpu_var(ksoftirqd); + + return tsk && !(tsk->state & (TASK_DEAD | TASK_ZOMBIE)); +} + /* * We restart softirq processing MAX_SOFTIRQ_RESTART times, * and we fall back to softirqd after that. @@ -69,7 +77,7 @@ */ #define MAX_SOFTIRQ_RESTART 10 -asmlinkage void do_softirq(void) +asmlinkage void __do_softirq(int from_ksoftirqd) { int max_restart = MAX_SOFTIRQ_RESTART; __u32 pending; @@ -86,6 +94,9 @@ struct softirq_action *h; local_bh_disable(); + + if (from_ksoftirqd && can_run_ksoftirqd()) + goto done; restart: /* Reset the pending bitmask before enabling irqs */ local_softirq_pending() = 0; @@ -106,6 +117,7 @@ pending = local_softirq_pending(); if (pending && --max_restart) goto restart; +done: if (pending) wakeup_softirqd(); __local_bh_enable(); @@ -114,6 +126,11 @@ local_irq_restore(flags); } +asmlinkage void do_softirq(void) +{ + __do_softirq(0); +} + EXPORT_SYMBOL(do_softirq); void local_bh_enable(void) @@ -324,7 +341,7 @@ __set_current_state(TASK_RUNNING); while (local_softirq_pending()) { - do_softirq(); + __do_softirq(1); cond_resched(); }