Merge branch 'smp-hotplug-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[cascardo/linux.git] / kernel / softirq.c
index c372114..6676264 100644 (file)
@@ -77,6 +77,17 @@ static void wakeup_softirqd(void)
                wake_up_process(tsk);
 }
 
+/*
+ * If ksoftirqd is scheduled, we do not want to process pending softirqs
+ * right now. Let ksoftirqd handle this at its own rate, to get fairness.
+ */
+static bool ksoftirqd_running(void)
+{
+       struct task_struct *tsk = __this_cpu_read(ksoftirqd);
+
+       return tsk && (tsk->state == TASK_RUNNING);
+}
+
 /*
  * preempt_count and SOFTIRQ_OFFSET usage:
  * - preempt_count is changed by SOFTIRQ_OFFSET on entering or leaving
@@ -313,7 +324,7 @@ asmlinkage __visible void do_softirq(void)
 
        pending = local_softirq_pending();
 
-       if (pending)
+       if (pending && !ksoftirqd_running())
                do_softirq_own_stack();
 
        local_irq_restore(flags);
@@ -340,6 +351,9 @@ void irq_enter(void)
 
 static inline void invoke_softirq(void)
 {
+       if (ksoftirqd_running())
+               return;
+
        if (!force_irqthreads) {
 #ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
                /*