]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
softirq: use ffs() in __do_softirq()
authorJoe Perches <joe@perches.com>
Fri, 3 Jan 2014 03:16:51 +0000 (14:16 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Mon, 6 Jan 2014 09:08:15 +0000 (20:08 +1100)
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>
kernel/softirq.c

index 937aa1f240c2eaf525d34731dfdb51b844b3c017..1945e1d701470d801310bbf0ff4498ad1b6c43ff 100644 (file)
@@ -252,6 +252,7 @@ asmlinkage void __do_softirq(void)
        struct softirq_action *h;
        bool in_hardirq;
        __u32 pending;
+       int softirq_bit;
        int cpu;
 
        /*
@@ -276,30 +277,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();