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:
		
				
					committed by
					
						
						Thomas Gleixner
					
				
			
			
				
	
			
			
			
						parent
						
							6498ddad30
						
					
				
				
					commit
					82b691bedf
				
			@@ -490,14 +490,16 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
 | 
			
		||||
}
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
	local_irq_disable();
 | 
			
		||||
	list = __this_cpu_read(tasklet_vec.head);
 | 
			
		||||
	__this_cpu_write(tasklet_vec.head, NULL);
 | 
			
		||||
	__this_cpu_write(tasklet_vec.tail, this_cpu_ptr(&tasklet_vec.head));
 | 
			
		||||
	list = tl_head->head;
 | 
			
		||||
	tl_head->head = NULL;
 | 
			
		||||
	tl_head->tail = &tl_head->head;
 | 
			
		||||
	local_irq_enable();
 | 
			
		||||
 | 
			
		||||
	while (list) {
 | 
			
		||||
@@ -519,47 +521,21 @@ static __latent_entropy void tasklet_action(struct softirq_action *a)
 | 
			
		||||
 | 
			
		||||
		local_irq_disable();
 | 
			
		||||
		t->next = NULL;
 | 
			
		||||
		*__this_cpu_read(tasklet_vec.tail) = t;
 | 
			
		||||
		__this_cpu_write(tasklet_vec.tail, &(t->next));
 | 
			
		||||
		__raise_softirq_irqoff(TASKLET_SOFTIRQ);
 | 
			
		||||
		*tl_head->tail = t;
 | 
			
		||||
		tl_head->tail = &t->next;
 | 
			
		||||
		__raise_softirq_irqoff(softirq_nr);
 | 
			
		||||
		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)
 | 
			
		||||
{
 | 
			
		||||
	struct tasklet_struct *list;
 | 
			
		||||
 | 
			
		||||
	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();
 | 
			
		||||
	}
 | 
			
		||||
	tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tasklet_init(struct tasklet_struct *t,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user