Re: [linux-audio-dev] Re: [announce] [patch] Voluntary Kernel Preemption Patch

Nick Piggin
2004-07-21T11:33:04Z

[-- Attachment #1: Type: text/plain, Size: 1176 bytes --]

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.

[-- Attachment #2: lat-softirq.patch --]
[-- Type: text/x-patch, Size: 3450 bytes --]

---

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 */

_