softirq: use ffs() in __do_softirq()
authorJoe Perches <joe@perches.com>
Tue, 28 Jan 2014 01:07:14 +0000 (17:07 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 28 Jan 2014 05:02:40 +0000 (21:02 -0800)
Possible speed improvement of __do_softirq() by using ffs() instead of
using a while loop with an & 1 test then single bit shift.

Signed-off-by: Joe Perches <joe@perches.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
kernel/softirq.c

index 8a1e6e1..ba79bbf 100644 (file)
@@ -229,6 +229,7 @@ asmlinkage void __do_softirq(void)
        struct softirq_action *h;
        bool in_hardirq;
        __u32 pending;
+       int softirq_bit;
        int cpu;
 
        /*
@@ -253,30 +254,30 @@ restart:
 
        h = softirq_vec;
 
-       do {
-               if (pending & 1) {
-                       unsigned int vec_nr = h - softirq_vec;
-                       int prev_count = preempt_count();
-
-                       kstat_incr_softirqs_this_cpu(vec_nr);
-
-                       trace_softirq_entry(vec_nr);
-                       h->action(h);
-                       trace_softirq_exit(vec_nr);
-                       if (unlikely(prev_count != preempt_count())) {
-                               printk(KERN_ERR "huh, entered softirq %u %s %p"
-                                      "with preempt_count %08x,"
-                                      " exited with %08x?\n", vec_nr,
-                                      softirq_to_name[vec_nr], h->action,
-                                      prev_count, preempt_count());
-                               preempt_count_set(prev_count);
-                       }
+       while ((softirq_bit = ffs(pending))) {
+               unsigned int vec_nr;
+               int prev_count;
+
+               h += softirq_bit - 1;
+
+               vec_nr = h - softirq_vec;
+               prev_count = preempt_count();
 
-                       rcu_bh_qs(cpu);
+               kstat_incr_softirqs_this_cpu(vec_nr);
+
+               trace_softirq_entry(vec_nr);
+               h->action(h);
+               trace_softirq_exit(vec_nr);
+               if (unlikely(prev_count != preempt_count())) {
+                       printk(KERN_ERR "huh, entered softirq %u %s %p with preempt_count %08x, exited with %08x?\n",
+                              vec_nr, softirq_to_name[vec_nr], h->action,
+                              prev_count, preempt_count());
+                       preempt_count_set(prev_count);
                }
+               rcu_bh_qs(cpu);
                h++;
-               pending >>= 1;
-       } while (pending);
+               pending >>= softirq_bit;
+       }
 
        local_irq_disable();