Messages in this thread Patch in this message | | | Date | Wed, 21 Jul 2004 21:32:46 +1000 | From | Nick Piggin <> | Subject | Re: [linux-audio-dev] Re: [announce] [patch] Voluntary Kernel Preemption Patch |
| |
Ingo Molnar wrote: >>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.) > > > i've got a more complete patch against vanilla 2.6.8-rc2: > > http://redhat.com/~mingo/voluntary-preempt/defer-softirqs-2.6.8-rc2-A2 > > which introduces the following tunable: > > /proc/sys/kernel/defer_softirqs (default: 0) > > this, if enabled, causes all softirqs to be processed within ksoftirqd, > and it also breaks out of the softirq loop if preemption of ksoftirqd > has been triggered by a higher-prio task. > > I've also added this additional break-out to the -H6 patch of > voluntary-preempt: > > http://redhat.com/~mingo/voluntary-preempt/voluntary-preempt-2.6.8-rc2-H6 > > it's enabled by default. >
What do you think about deferring softirqs just while in critical sections?
I'm not sure how well this works, and it is CONFIG_PREEMPT only but in theory it should prevent unbounded softirqs while under locks without taking the performance hit of doing the context switch.
---
linux-2.6-npiggin/include/asm-i386/hardirq.h | 8 ++++++-- linux-2.6-npiggin/include/linux/preempt.h | 6 +----- linux-2.6-npiggin/kernel/sched.c | 13 +++++++++++-- linux-2.6-npiggin/kernel/softirq.c | 4 ++-- 4 files changed, 20 insertions(+), 11 deletions(-)
diff -puN kernel/softirq.c~lat-softirq kernel/softirq.c --- linux-2.6/kernel/softirq.c~lat-softirq 2004-07-17 00:32:52.000000000 +1000 +++ linux-2.6-npiggin/kernel/softirq.c 2004-07-17 00:32:52.000000000 +1000 @@ -68,7 +68,7 @@ static inline void wakeup_softirqd(void) * we want to handle softirqs as soon as possible, but they * should not be able to lock up the box. */ -#define MAX_SOFTIRQ_RESTART 10 +#define MAX_SOFTIRQ_RESTART 4 asmlinkage void __do_softirq(void) { @@ -322,7 +322,7 @@ void __init softirq_init(void) static int ksoftirqd(void * __bind_cpu) { - set_user_nice(current, 19); + set_user_nice(current, 10); current->flags |= PF_NOFREEZE; set_current_state(TASK_INTERRUPTIBLE); diff -puN include/asm-i386/hardirq.h~lat-softirq include/asm-i386/hardirq.h --- linux-2.6/include/asm-i386/hardirq.h~lat-softirq 2004-07-17 00:32:52.000000000 +1000 +++ linux-2.6-npiggin/include/asm-i386/hardirq.h 2004-07-17 00:32:52.000000000 +1000 @@ -80,17 +80,21 @@ typedef struct { # include <linux/smp_lock.h> # define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked()) # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1) +#define irq_exit() \ +do { \ + preempt_count() -= IRQ_EXIT_OFFSET; \ + preempt_enable_no_resched(); /* This will catch the softirq */ \ +} while (0) #else # define in_atomic() (preempt_count() != 0) # define IRQ_EXIT_OFFSET HARDIRQ_OFFSET -#endif #define irq_exit() \ do { \ preempt_count() -= IRQ_EXIT_OFFSET; \ if (!in_interrupt() && softirq_pending(smp_processor_id())) \ do_softirq(); \ - preempt_enable_no_resched(); \ } while (0) +#endif #ifndef CONFIG_SMP # define synchronize_irq(irq) barrier() diff -puN include/linux/preempt.h~lat-softirq include/linux/preempt.h --- linux-2.6/include/linux/preempt.h~lat-softirq 2004-07-17 00:32:52.000000000 +1000 +++ linux-2.6-npiggin/include/linux/preempt.h 2004-07-17 00:32:52.000000000 +1000 @@ -16,12 +16,8 @@ do { \ preempt_count()++; \ } while (0) -#define dec_preempt_count() \ -do { \ - preempt_count()--; \ -} while (0) - #ifdef CONFIG_PREEMPT +void dec_preempt_count(void); asmlinkage void preempt_schedule(void); diff -puN kernel/sched.c~lat-softirq kernel/sched.c --- linux-2.6/kernel/sched.c~lat-softirq 2004-07-17 00:32:52.000000000 +1000 +++ linux-2.6-npiggin/kernel/sched.c 2004-07-17 00:32:52.000000000 +1000 @@ -3968,8 +3968,16 @@ void __might_sleep(char *file, int line) EXPORT_SYMBOL(__might_sleep); #endif +#ifdef CONFIG_PREEMPT +void dec_preempt_count(void) +{ + if (unlikely(preempt_count() == 1 && + softirq_pending(smp_processor_id()))) + do_softirq(); + preempt_count()--; +} -#if defined(CONFIG_SMP) && defined(CONFIG_PREEMPT) +#ifdef CONFIG_SMP /* * This could be a long-held lock. If another CPU holds it for a long time, * and that CPU is not asked to reschedule then *this* CPU will spin on the @@ -4012,4 +4020,5 @@ void __sched __preempt_write_lock(rwlock } EXPORT_SYMBOL(__preempt_write_lock); -#endif /* defined(CONFIG_SMP) && defined(CONFIG_PREEMPT) */ +#endif /* CONFIG_SMP */ +#endif /* CONFIG_PREEMPT */ _
| |