On Thu, 2015-04-16 at 18:28 +0200, Jan Kiszka wrote: > Instead of turning all irq_work requests into lazy ones on -rt, just > move their execution from hard into soft-irq context. > > This resolves deadlocks of ftrace which will queue work from > arbitrary > contexts, including those that have locks held that are needed for > raising a soft-irq. Yup, trace-cmd record -> dead-box fully repeatable, and now fixed. > Signed-off-by: Jan Kiszka <jan.kiszka@xxxxxxxxxxx> > --- > > Second try, looks much better so far. And it also removes my concerns > regarding other potential cases besides ftrace. > > kernel/irq_work.c | 26 ++++++++++---------------- > 1 file changed, 10 insertions(+), 16 deletions(-) > > diff --git a/kernel/irq_work.c b/kernel/irq_work.c > index 9dda38a..3f6ffcd 100644 > --- a/kernel/irq_work.c > +++ b/kernel/irq_work.c > @@ -85,12 +85,9 @@ bool irq_work_queue_on(struct irq_work *work, int > cpu) > raise_irqwork = llist_add(&work->llnode, > &per_cpu(hirq_work_list, cpu)); > else > - raise_irqwork = llist_add(&work->llnode, > - &per_cpu(lazy_list, cpu)); > -#else > +#endif > raise_irqwork = llist_add(&work->llnode, > &per_cpu(raised_list, cpu)); > -#endif > > if (raise_irqwork) > arch_send_call_function_single_ipi(cpu); > @@ -114,21 +111,20 @@ bool irq_work_queue(struct irq_work *work) > if (work->flags & IRQ_WORK_HARD_IRQ) { > if (llist_add(&work->llnode, this_cpu_ptr(&hirq_work_list))) > arch_irq_work_raise(); > - } else { > + } else > +#endif > + if (work->flags & IRQ_WORK_LAZY) { > if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) && > tick_nohz_tick_stopped()) > +#ifdef CONFIG_PREEMPT_RT_FULL > raise_softirq(TIMER_SOFTIRQ); > - } > #else > - if (work->flags & IRQ_WORK_LAZY) { > - if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) && > - tick_nohz_tick_stopped()) > arch_irq_work_raise(); > +#endif > } else { > if (llist_add(&work->llnode, this_cpu_ptr(&raised_list))) > arch_irq_work_raise(); > } > -#endif > > preempt_enable(); > > @@ -202,6 +198,8 @@ void irq_work_run(void) > { > #ifdef CONFIG_PREEMPT_RT_FULL > irq_work_run_list(this_cpu_ptr(&hirq_work_list)); > + if (!llist_empty(this_cpu_ptr(&raised_list))) > + raise_softirq(TIMER_SOFTIRQ); > #else > irq_work_run_list(this_cpu_ptr(&raised_list)); > irq_work_run_list(this_cpu_ptr(&lazy_list)); > @@ -211,15 +209,11 @@ EXPORT_SYMBOL_GPL(irq_work_run); > > void irq_work_tick(void) > { > -#ifdef CONFIG_PREEMPT_RT_FULL > - irq_work_run_list(this_cpu_ptr(&lazy_list)); > -#else > - struct llist_head *raised = &__get_cpu_var(raised_list); > + struct llist_head *raised = this_cpu_ptr(&raised_list); > > if (!llist_empty(raised) && !arch_irq_work_has_interrupt()) > irq_work_run_list(raised); > - irq_work_run_list(&__get_cpu_var(lazy_list)); > -#endif > + irq_work_run_list(this_cpu_ptr(&lazy_list)); > } > > /* -- To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html