lkml.org 
[lkml]   [2001]   [May]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
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
\
 
 \ /
  Last update: 2005-03-22 12:54    [from the cache]
©2003-2011 Jasper Spaans