History

irq_work: Also rcuwait for !IRQ_WORK_HARD_IRQ on PREEMPT_RT

On PREEMPT_RT most items are processed as LAZY via softirq context. Avoid to spin-wait for them because irq_work_sync() could have higher priority and not allow the irq-work to be completed. Wait additionally for !IRQ_WORK_HARD_IRQ irq_work items on PREEMPT_RT.

Sebastian Andrzej Siewior committed 5 years ago

Commit 09089db1 parent b4c6f862 files · +9 −2Browse files

Unified · Split

2 files
  1. include/linux/irq_work.h +5 −0
  2. kernel/irq_work.c +4 −2
include/linux/irq_work.h+5−0
@@ -49,6 +49,11 @@ static inline bool irq_work_is_busy(struct irq_work *work) · 48 unmodified lines
4949 return atomic_read(&work->node.a_flags) & IRQ_WORK_BUSY;
5050 }
5151
52+static inline bool irq_work_is_hard(struct irq_work *work)
53+{
54+ return atomic_read(&work->node.a_flags) & IRQ_WORK_HARD_IRQ;
55+}
56+
5257 bool irq_work_queue(struct irq_work *work);
5358 bool irq_work_queue_on(struct irq_work *work, int cpu);
5459
kernel/irq_work.c+4−2
@@ -217,7 +217,8 @@ void irq_work_single(void *arg) · 216 unmodified lines
217217 */
218218 (void)atomic_cmpxchg(&work->node.a_flags, flags, flags & ~IRQ_WORK_BUSY);
219219
220− if (!arch_irq_work_has_interrupt())
220+ if ((IS_ENABLED(CONFIG_PREEMPT_RT) && !irq_work_is_hard(work)) ||
221+ !arch_irq_work_has_interrupt())
221222 rcuwait_wake_up(&work->irqwait);
222223 }
223224
@@ -277,7 +278,8 @@ void irq_work_sync(struct irq_work *work) · 53 unmodified lines
277278 lockdep_assert_irqs_enabled();
278279 might_sleep();
279280
280− if (!arch_irq_work_has_interrupt()) {
281+ if ((IS_ENABLED(CONFIG_PREEMPT_RT) && !irq_work_is_hard(work)) ||
282+ !arch_irq_work_has_interrupt()) {
281283 rcuwait_wait_event(&work->irqwait, !irq_work_is_busy(work),
282284 TASK_UNINTERRUPTIBLE);
283285 return;