diff options
author | Tim Chen <tim.c.chen@linux.intel.com> | 2006-07-30 06:04:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-31 16:28:42 -0400 |
commit | 3c829c367a1a52550378584a657768217971e587 (patch) | |
tree | 78dfcbe28e6a0db56992ce5ad5891398a9743bf4 | |
parent | 953a7f20667a8b6217ea2ac49c0877e957a0130a (diff) |
[PATCH] Reducing local_bh_enable/disable overhead in irqtrace
The recent changes from irqtrace feature has added overheads to
local_bh_disable and local_bh_enable that reduces UDP performance across
x86_64 and IA64, even though IA64 does not support the irqtrace feature.
Patch in question is
[PATCH]lockdep: irqtrace subsystem, core
http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=c
ommit;h=de30a2b355ea85350ca2f58f3b9bf4e5bc007986
Prior to this patch, local_bh_disable was a short macro. Now it is a
function which calls __local_bh_disable with added irq flags save and
restore. The irq flags save and restore were also added to
local_bh_enable, probably for injecting the trace irqs code.
This overhead is on the generic code path across all architectures. On a
IA_64 test machine (Itanium-2 1.6 GHz) running a benchmark like netperf's
UDP streaming test, the added overhead results in a drop of 3% in
throughput, as udp_sendmsg calls the local_bh_enable/disable several times.
Other workloads that have heavy usages of local_bh_enable/disable could
also be affected. The patch ideally should not have affected IA-64
performance as it does not have IRQ tracing support. A significant portion
of the overhead is in the added irq flags save and restore, which I think
is not needed if IRQ tracing is unused. A suggested patch is attached
below that recovers the lost performance. However, the "ifdef"s in the
patch are a bit ugly.
Signed-off-by: Tim Chen <tim.c.chen@intel.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | kernel/softirq.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c index aab880677ce0..3789ca98197c 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c | |||
@@ -65,6 +65,7 @@ static inline void wakeup_softirqd(void) | |||
65 | * This one is for softirq.c-internal use, | 65 | * This one is for softirq.c-internal use, |
66 | * where hardirqs are disabled legitimately: | 66 | * where hardirqs are disabled legitimately: |
67 | */ | 67 | */ |
68 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
68 | static void __local_bh_disable(unsigned long ip) | 69 | static void __local_bh_disable(unsigned long ip) |
69 | { | 70 | { |
70 | unsigned long flags; | 71 | unsigned long flags; |
@@ -80,6 +81,13 @@ static void __local_bh_disable(unsigned long ip) | |||
80 | trace_softirqs_off(ip); | 81 | trace_softirqs_off(ip); |
81 | raw_local_irq_restore(flags); | 82 | raw_local_irq_restore(flags); |
82 | } | 83 | } |
84 | #else /* !CONFIG_TRACE_IRQFLAGS */ | ||
85 | static inline void __local_bh_disable(unsigned long ip) | ||
86 | { | ||
87 | add_preempt_count(SOFTIRQ_OFFSET); | ||
88 | barrier(); | ||
89 | } | ||
90 | #endif /* CONFIG_TRACE_IRQFLAGS */ | ||
83 | 91 | ||
84 | void local_bh_disable(void) | 92 | void local_bh_disable(void) |
85 | { | 93 | { |
@@ -121,12 +129,16 @@ EXPORT_SYMBOL(_local_bh_enable); | |||
121 | 129 | ||
122 | void local_bh_enable(void) | 130 | void local_bh_enable(void) |
123 | { | 131 | { |
132 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
124 | unsigned long flags; | 133 | unsigned long flags; |
125 | 134 | ||
126 | WARN_ON_ONCE(in_irq()); | 135 | WARN_ON_ONCE(in_irq()); |
136 | #endif | ||
127 | WARN_ON_ONCE(irqs_disabled()); | 137 | WARN_ON_ONCE(irqs_disabled()); |
128 | 138 | ||
139 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
129 | local_irq_save(flags); | 140 | local_irq_save(flags); |
141 | #endif | ||
130 | /* | 142 | /* |
131 | * Are softirqs going to be turned on now: | 143 | * Are softirqs going to be turned on now: |
132 | */ | 144 | */ |
@@ -142,18 +154,22 @@ void local_bh_enable(void) | |||
142 | do_softirq(); | 154 | do_softirq(); |
143 | 155 | ||
144 | dec_preempt_count(); | 156 | dec_preempt_count(); |
157 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
145 | local_irq_restore(flags); | 158 | local_irq_restore(flags); |
159 | #endif | ||
146 | preempt_check_resched(); | 160 | preempt_check_resched(); |
147 | } | 161 | } |
148 | EXPORT_SYMBOL(local_bh_enable); | 162 | EXPORT_SYMBOL(local_bh_enable); |
149 | 163 | ||
150 | void local_bh_enable_ip(unsigned long ip) | 164 | void local_bh_enable_ip(unsigned long ip) |
151 | { | 165 | { |
166 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
152 | unsigned long flags; | 167 | unsigned long flags; |
153 | 168 | ||
154 | WARN_ON_ONCE(in_irq()); | 169 | WARN_ON_ONCE(in_irq()); |
155 | 170 | ||
156 | local_irq_save(flags); | 171 | local_irq_save(flags); |
172 | #endif | ||
157 | /* | 173 | /* |
158 | * Are softirqs going to be turned on now: | 174 | * Are softirqs going to be turned on now: |
159 | */ | 175 | */ |
@@ -169,7 +185,9 @@ void local_bh_enable_ip(unsigned long ip) | |||
169 | do_softirq(); | 185 | do_softirq(); |
170 | 186 | ||
171 | dec_preempt_count(); | 187 | dec_preempt_count(); |
188 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
172 | local_irq_restore(flags); | 189 | local_irq_restore(flags); |
190 | #endif | ||
173 | preempt_check_resched(); | 191 | preempt_check_resched(); |
174 | } | 192 | } |
175 | EXPORT_SYMBOL(local_bh_enable_ip); | 193 | EXPORT_SYMBOL(local_bh_enable_ip); |