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
49 return atomic_read(&work->node.a_flags) & IRQ_WORK_BUSY;49 return atomic_read(&work->node.a_flags) & IRQ_WORK_BUSY;
50}50}
51 51
52static 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
52bool irq_work_queue(struct irq_work *work);57bool irq_work_queue(struct irq_work *work);
53bool irq_work_queue_on(struct irq_work *work, int cpu);58bool irq_work_queue_on(struct irq_work *work, int cpu);
54 59
kernel/irq_work.c+4−2
@@ -217,7 +217,8 @@ void irq_work_single(void *arg) · 216 unmodified lines
217 */217 */
218 (void)atomic_cmpxchg(&work->node.a_flags, flags, flags & ~IRQ_WORK_BUSY);218 (void)atomic_cmpxchg(&work->node.a_flags, flags, flags & ~IRQ_WORK_BUSY);
219 219
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())
221 rcuwait_wake_up(&work->irqwait);222 rcuwait_wake_up(&work->irqwait);
222}223}
223 224
@@ -277,7 +278,8 @@ void irq_work_sync(struct irq_work *work) · 53 unmodified lines
277 lockdep_assert_irqs_enabled();278 lockdep_assert_irqs_enabled();
278 might_sleep();279 might_sleep();
279 280
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()) {
281 rcuwait_wait_event(&work->irqwait, !irq_work_is_busy(work),283 rcuwait_wait_event(&work->irqwait, !irq_work_is_busy(work),
282 TASK_UNINTERRUPTIBLE);284 TASK_UNINTERRUPTIBLE);
283 return;285 return;