Messages in this thread Patch in this message |  | | | Date | Sun, 27 May 2001 21:00:35 +0200 (CEST) | | From | Ingo Molnar <> | | Subject | [patch] softirq-2.4.5-B0 |
| |
On Sat, 26 May 2001, David S. Miller wrote:
> And looking at the x86 code, I don't even understand how your fixes > can make a difference, what about the do_softirq() call in > arch/i386/kernel/irq.c:do_IRQ()??? [...]
[you are right, it's a brain fart on my part. doh. i guess i was too happy having fixed the longstanding latency problem.]
the TCP latency issues and the missed softirq execution bug is still there, but for a slightly different reason.
the bug/misbehavior causing bad latencies turned out to be the following: if a hardirq triggers a softirq, but syscall-level code on the same CPU disabled local bhs via local_bh_disable(), then we 'miss' the execution of the softirq, until the next IRQ. (or next direct call to do_softirq()).
the attached softirq-2.4.5-B0 patch fixes this problem by calling do_softirq() from local_bh_enable() [if the bh count is 0, to avoid recursion]. This slightly changes local_bh_enable() semantics: calling do_softirq() has the side-effect of disabling/enabling interrupts, so code that used local_bh_enable while interrupts are disabled (and depended on them staying disabled) will break. I checked all code that uses local_bh_enable() via a debugging check, and the only (harmless) violation of this new rule is machine_restart() in the x86 tree.
Yesterday's patches fix this problem too, but only as a lucky side-effect, and only in the idle-poll case. 2.4.5 + softirq-2.4.5-B0 TCP latency is down from a fluctuating 300-400 microseconds to a stable 109 microseconds.
Ingo --- linux/kernel/softirq.c.orig Sun May 27 20:57:36 2001 +++ linux/kernel/softirq.c Sun May 27 20:57:52 2001 @@ -87,7 +87,7 @@ goto retry; } - local_bh_enable(); + __local_bh_enable(); /* Leave with locally disabled hard irqs. It is critical to close * window for infinite recursion, while we help local bh count, --- linux/include/asm-i386/softirq.h.orig Sun May 27 20:56:58 2001 +++ linux/include/asm-i386/softirq.h Sun May 27 20:58:15 2001 @@ -5,10 +5,12 @@ #include <asm/hardirq.h> #define cpu_bh_disable(cpu) do { local_bh_count(cpu)++; barrier(); } while (0) -#define cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--; } while (0) +#define __cpu_bh_enable(cpu) do { barrier(); local_bh_count(cpu)--; } while (0) +extern void cpu_bh_enable (unsigned int cpu); #define local_bh_disable() cpu_bh_disable(smp_processor_id()) #define local_bh_enable() cpu_bh_enable(smp_processor_id()) +#define __local_bh_enable() __cpu_bh_enable(smp_processor_id()) #define in_softirq() (local_bh_count(smp_processor_id()) != 0) --- linux/arch/i386/kernel/irq.c.orig Sun May 27 20:55:08 2001 +++ linux/arch/i386/kernel/irq.c Sun May 27 20:56:45 2001 @@ -628,6 +628,19 @@ return 1; } +/* + * A bh-atomic section might have blocked the execution of softirqs. + * re-run them if appropriate. + */ +void cpu_bh_enable (unsigned int cpu) +{ + if (!--local_bh_count(cpu) && + (softirq_active(cpu) & softirq_mask(cpu))) { + do_softirq(); + __sti(); + } +} + /** * request_irq - allocate an interrupt line * @irq: Interrupt line to allocate
|  |