softirq: Consolidate common code in tasklet_[hi]_action()
tasklet_action() + tasklet_hi_action() are almost identical. Move the common code from both function into __tasklet_action_common() and let both functions invoke it with different arguments. [ bigeasy: Splitted out from RT's "tasklet: Prevent tasklets from going into infinite spin in RT" and added commit message] Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Julia Cartwright <juliac@eso.teric.us> Link: https://lkml.kernel.org/r/20180227164808.10093-3-bigeasy@linutronix.de
This commit is contained in:
parent
6498ddad30
commit
82b691bedf
@ -490,14 +490,16 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__tasklet_hi_schedule);
|
EXPORT_SYMBOL(__tasklet_hi_schedule);
|
||||||
|
|
||||||
static __latent_entropy void tasklet_action(struct softirq_action *a)
|
static void tasklet_action_common(struct softirq_action *a,
|
||||||
|
struct tasklet_head *tl_head,
|
||||||
|
unsigned int softirq_nr)
|
||||||
{
|
{
|
||||||
struct tasklet_struct *list;
|
struct tasklet_struct *list;
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
list = __this_cpu_read(tasklet_vec.head);
|
list = tl_head->head;
|
||||||
__this_cpu_write(tasklet_vec.head, NULL);
|
tl_head->head = NULL;
|
||||||
__this_cpu_write(tasklet_vec.tail, this_cpu_ptr(&tasklet_vec.head));
|
tl_head->tail = &tl_head->head;
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
|
||||||
while (list) {
|
while (list) {
|
||||||
@ -519,47 +521,21 @@ static __latent_entropy void tasklet_action(struct softirq_action *a)
|
|||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
t->next = NULL;
|
t->next = NULL;
|
||||||
*__this_cpu_read(tasklet_vec.tail) = t;
|
*tl_head->tail = t;
|
||||||
__this_cpu_write(tasklet_vec.tail, &(t->next));
|
tl_head->tail = &t->next;
|
||||||
__raise_softirq_irqoff(TASKLET_SOFTIRQ);
|
__raise_softirq_irqoff(softirq_nr);
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static __latent_entropy void tasklet_action(struct softirq_action *a)
|
||||||
|
{
|
||||||
|
tasklet_action_common(a, this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ);
|
||||||
|
}
|
||||||
|
|
||||||
static __latent_entropy void tasklet_hi_action(struct softirq_action *a)
|
static __latent_entropy void tasklet_hi_action(struct softirq_action *a)
|
||||||
{
|
{
|
||||||
struct tasklet_struct *list;
|
tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);
|
||||||
|
|
||||||
local_irq_disable();
|
|
||||||
list = __this_cpu_read(tasklet_hi_vec.head);
|
|
||||||
__this_cpu_write(tasklet_hi_vec.head, NULL);
|
|
||||||
__this_cpu_write(tasklet_hi_vec.tail, this_cpu_ptr(&tasklet_hi_vec.head));
|
|
||||||
local_irq_enable();
|
|
||||||
|
|
||||||
while (list) {
|
|
||||||
struct tasklet_struct *t = list;
|
|
||||||
|
|
||||||
list = list->next;
|
|
||||||
|
|
||||||
if (tasklet_trylock(t)) {
|
|
||||||
if (!atomic_read(&t->count)) {
|
|
||||||
if (!test_and_clear_bit(TASKLET_STATE_SCHED,
|
|
||||||
&t->state))
|
|
||||||
BUG();
|
|
||||||
t->func(t->data);
|
|
||||||
tasklet_unlock(t);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
tasklet_unlock(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
local_irq_disable();
|
|
||||||
t->next = NULL;
|
|
||||||
*__this_cpu_read(tasklet_hi_vec.tail) = t;
|
|
||||||
__this_cpu_write(tasklet_hi_vec.tail, &(t->next));
|
|
||||||
__raise_softirq_irqoff(HI_SOFTIRQ);
|
|
||||||
local_irq_enable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tasklet_init(struct tasklet_struct *t,
|
void tasklet_init(struct tasklet_struct *t,
|
||||||
|
Loading…
Reference in New Issue
Block a user