diff options
Diffstat (limited to 'kernel/softirq.c')
| -rw-r--r-- | kernel/softirq.c | 82 | 
1 files changed, 31 insertions, 51 deletions
| diff --git a/kernel/softirq.c b/kernel/softirq.c index 24d243ef8e71..177de3640c78 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -460,40 +460,46 @@ struct tasklet_head {  static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);  static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec); -void __tasklet_schedule(struct tasklet_struct *t) +static void __tasklet_schedule_common(struct tasklet_struct *t, +				      struct tasklet_head __percpu *headp, +				      unsigned int softirq_nr)  { +	struct tasklet_head *head;  	unsigned long flags;  	local_irq_save(flags); +	head = this_cpu_ptr(headp);  	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, &tasklet_vec, +				  TASKLET_SOFTIRQ); +}  EXPORT_SYMBOL(__tasklet_schedule);  void __tasklet_hi_schedule(struct tasklet_struct *t)  { -	unsigned long flags; - -	local_irq_save(flags); -	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_restore(flags); +	__tasklet_schedule_common(t, &tasklet_hi_vec, +				  HI_SOFTIRQ);  }  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) { @@ -515,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_hi_action(struct softirq_action *a) +static __latent_entropy void tasklet_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); -		} +	tasklet_action_common(a, this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ); +} -		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(); -	} +static __latent_entropy void tasklet_hi_action(struct softirq_action *a) +{ +	tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);  }  void tasklet_init(struct tasklet_struct *t, | 
