|
|
@@ -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
|
|
|
/*
|