Re: [reiserfs-list] Re: [PATCH] Significant performace improvements on reiserfs systems

Rusty Russell
2001-09-23T23:55:23Z

On Fri, 21 Sep 2001 13:18:31 +0100 (BST)
Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:

> > In Solaris, before spinning on a busy spin-lock, thread checks whether
> > spin-lock holder runs on the same processor. If so, thread goes to sleep
> > and holder wakes it up on spin-lock release. The same, I guess is going
>
>
> > for interrupts that are served as separate threads. This way, one can
> > re-schedule with spin-locks held.
>
> This is one of the things interrupt handling by threads gives you, but the
> performance cost is not nice. When you consider that ksoftirqd when it
> kicks in (currently far too often) takes up to 10% off gigabit ethernet
> performance, you can appreciate why we don't want to go that path.

I've been thinking about this: I know some people have been fiddling with making
do_softirq spin X times before kicking ksoftirqd, but how about the following?

Cheers,
Rusty.

--- linux-pmac/kernel/softirq.c Sun Sep 9 15:11:37 2001
+++ working-pmac-ksoftirq/kernel/softirq.c Mon Sep 24 09:44:07 2001
@@ -63,11 +63,12 @@
int cpu = smp_processor_id();
__u32 pending;
long flags;
- __u32 mask;
+ long start;

if (in_interrupt())
return;

+ start = jiffies;
local_irq_save(flags);

pending = softirq_pending(cpu);
@@ -75,32 +76,32 @@
if (pending) {
struct softirq_action *h;

- mask = ~pending;
local_bh_disable();
-restart:
- /* Reset the pending bitmask before enabling irqs */
- softirq_pending(cpu) = 0;
+ do {
+ /* Reset the pending bitmask before enabling irqs */
+ softirq_pending(cpu) = 0;

- local_irq_enable();
+ local_irq_enable();

- h = softirq_vec;
+ h = softirq_vec;

- do {
- if (pending & 1)
- h->action(h);
- h++;
- pending >>= 1;
- } while (pending);
-
- local_irq_disable();
-
- pending = softirq_pending(cpu);
- if (pending & mask) {
- mask &= ~pending;
- goto restart;
- }
+ do {
+ if (pending & 1)
+ h->action(h);
+ h++;
+ pending >>= 1;
+ } while (pending);
+
+ local_irq_disable();
+
+ pending = softirq_pending(cpu);
+
+ /* Don't spin here forever... */
+ } while (pending && start == jiffies);
__local_bh_enable();

+ /* If a timer tick went off, assume we're overloaded,
+ and kick in ksoftirqd */
if (pending)
wakeup_softirqd(cpu);
}