* Lee Revell <rlrevell(a)joe-job.com> wrote:
I can also add that La Monte H. P. Yarroll's patch
to daemonize
softirqs seems to provide major improvements in latency (does not help
this problem of course). There has been at least one other patch
posted to LKML that that does the same thing. Will this feature be in
the kernel anytime soon?
we already 'daemonize' softirqs in the stock kernel if the load is high
enough. (this is what ksoftirqd does) So the only question is a tunable
to make this deferring of softirq load mandatory. Yarroll's patch is
quite complex, i dont think that is necessary. It also has at least one
conceptual problem, the NOP-ing of local_bh_disable/enable in case of
CONFIG_SOFTIRQ_THREADS is clearly wrong. Yarroll?
I've added a very simple solution to daemonize softirqs similar to
Yarroll's patch to the -H5 version of voluntary-preempt:
http://redhat.com/~mingo/voluntary-preempt/voluntary-preempt-2.6.8-rc2-H5
the 'level' of preemption is controlled via the value of
voluntary_preempt - a level of 2 (default) means that softirq-deferring
is done too. A level of 1 means only the extra preemption points are
activated, level 0 means the vanilla scheduling and softirq behavior.
below i've also attached a softirq.c patch against 2.6.8-rc2 that does
unconditional deferring. (this patch is of course not intended to be
merged upstream as-is, since normally we want to process softirqs right
after the irq context.)
Ingo
--- linux/kernel/softirq.c.orig
+++ linux/kernel/softirq.c
@@ -70,7 +70,7 @@ static inline void wakeup_softirqd(void)
*/
#define MAX_SOFTIRQ_RESTART 10
-asmlinkage void __do_softirq(void)
+asmlinkage void ___do_softirq(void)
{
struct softirq_action *h;
__u32 pending;
@@ -106,6 +106,23 @@ restart:
__local_bh_enable();
}
+asmlinkage void __do_softirq(void)
+{
+ /*
+ * 'preempt harder'. Push all softirq processing off to ksoftirqd.
+ */
+ if (local_softirq_pending())
+ wakeup_softirqd();
+}
+
+asmlinkage void _do_softirq(void)
+{
+ local_irq_disable();
+ ___do_softirq();
+ local_irq_enable();
+}
+
+
#ifndef __ARCH_HAS_DO_SOFTIRQ
asmlinkage void do_softirq(void)
@@ -340,7 +363,7 @@ static int ksoftirqd(void * __bind_cpu)
preempt_disable();
if (cpu_is_offline((long)__bind_cpu))
goto wait_to_die;
- do_softirq();
+ _do_softirq();
preempt_enable();
cond_resched();
}