summaryrefslogtreecommitdiffstats
path: root/kernel/softirq.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2018-02-27 11:48:08 -0500
committerThomas Gleixner <tglx@linutronix.de>2018-03-09 05:50:55 -0500
commit82b691bedf05f258f1c86c96ee574b0d7795c0a1 (patch)
treed97728fa77c736941fbcf7e0792f54bfe9bbf4c2 /kernel/softirq.c
parent6498ddad301c7a94162915d06d1efe2e5d20f6dc (diff)
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
Diffstat (limited to 'kernel/softirq.c')
-rw-r--r--kernel/softirq.c54
1 files changed, 15 insertions, 39 deletions
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 2394b009994f..177de3640c78 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -490,14 +490,16 @@ void __tasklet_hi_schedule(struct tasklet_struct *t)
490} 490}
491EXPORT_SYMBOL(__tasklet_hi_schedule); 491EXPORT_SYMBOL(__tasklet_hi_schedule);
492 492
493static __latent_entropy void tasklet_action(struct softirq_action *a) 493static void tasklet_action_common(struct softirq_action *a,
494 struct tasklet_head *tl_head,
495 unsigned int softirq_nr)
494{ 496{
495 struct tasklet_struct *list; 497 struct tasklet_struct *list;
496 498
497 local_irq_disable(); 499 local_irq_disable();
498 list = __this_cpu_read(tasklet_vec.head); 500 list = tl_head->head;
499 __this_cpu_write(tasklet_vec.head, NULL); 501 tl_head->head = NULL;
500 __this_cpu_write(tasklet_vec.tail, this_cpu_ptr(&tasklet_vec.head)); 502 tl_head->tail = &tl_head->head;
501 local_irq_enable(); 503 local_irq_enable();
502 504
503 while (list) { 505 while (list) {
@@ -519,47 +521,21 @@ static __latent_entropy void tasklet_action(struct softirq_action *a)
519 521
520 local_irq_disable(); 522 local_irq_disable();
521 t->next = NULL; 523 t->next = NULL;
522 *__this_cpu_read(tasklet_vec.tail) = t; 524 *tl_head->tail = t;
523 __this_cpu_write(tasklet_vec.tail, &(t->next)); 525 tl_head->tail = &t->next;
524 __raise_softirq_irqoff(TASKLET_SOFTIRQ); 526 __raise_softirq_irqoff(softirq_nr);
525 local_irq_enable(); 527 local_irq_enable();
526 } 528 }
527} 529}
528 530
529static __latent_entropy void tasklet_hi_action(struct softirq_action *a) 531static __latent_entropy void tasklet_action(struct softirq_action *a)
530{ 532{
531 struct tasklet_struct *list; 533 tasklet_action_common(a, this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ);
532 534}
533 local_irq_disable();
534 list = __this_cpu_read(tasklet_hi_vec.head);
535 __this_cpu_write(tasklet_hi_vec.head, NULL);
536 __this_cpu_write(tasklet_hi_vec.tail, this_cpu_ptr(&tasklet_hi_vec.head));
537 local_irq_enable();
538
539 while (list) {
540 struct tasklet_struct *t = list;
541
542 list = list->next;
543
544 if (tasklet_trylock(t)) {
545 if (!atomic_read(&t->count)) {
546 if (!test_and_clear_bit(TASKLET_STATE_SCHED,
547 &t->state))
548 BUG();
549 t->func(t->data);
550 tasklet_unlock(t);
551 continue;
552 }
553 tasklet_unlock(t);
554 }
555 535
556 local_irq_disable(); 536static __latent_entropy void tasklet_hi_action(struct softirq_action *a)
557 t->next = NULL; 537{
558 *__this_cpu_read(tasklet_hi_vec.tail) = t; 538 tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);
559 __this_cpu_write(tasklet_hi_vec.tail, &(t->next));
560 __raise_softirq_irqoff(HI_SOFTIRQ);
561 local_irq_enable();
562 }
563} 539}
564 540
565void tasklet_init(struct tasklet_struct *t, 541void tasklet_init(struct tasklet_struct *t,