Messages in this thread | | | Date | Thu, 15 Feb 2018 15:07:07 -0500 | From | Steven Rostedt <> | Subject | Re: [PATCH 1/2] kernel/sofirq: consolidate common code in __tasklet_schedule() + _hi_ |
| |
On Thu, 15 Feb 2018 18:20:41 +0100 Sebastian Andrzej Siewior <bigeasy@linutronix.de> wrote:
> -void __tasklet_schedule(struct tasklet_struct *t) > +static void __tasklet_schedule_common(struct tasklet_struct *t, > + struct tasklet_head *head, > + unsigned int softirq_nr) > { > unsigned long flags; > > local_irq_save(flags);
If you look at the original patch, it did not move local_irq_save() into the common function.
> t->next = NULL; > - *__this_cpu_read(tasklet_vec.tail) = t; > - __this_cpu_write(tasklet_vec.tail, &(t->next)); > - raise_softirq_irqoff(TASKLET_SOFTIRQ); > + *head->tail = t; > + head->tail = &(t->next); > + raise_softirq_irqoff(softirq_nr); > local_irq_restore(flags); > } > + > +void __tasklet_schedule(struct tasklet_struct *t) > +{ > + __tasklet_schedule_common(t, this_cpu_ptr(&tasklet_vec),
What can happen is, we reference (tasklet_vec) on one CPU, get preempted (running in ksoftirqd), scheduled on another CPU, then when inside the common code, we are executing on a different CPU than the tasklet is for. The rasise_softirq() is happening on the wrong CPU.
The local_irq_save() can't be moved to the common function. It must be done by each individual function.
-- Steve
> + TASKLET_SOFTIRQ); > +} > EXPORT_SYMBOL(__tasklet_schedule);
| |