diff options
author | Ingo Molnar <mingo@kernel.org> | 2018-02-27 11:48:08 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2018-03-09 05:50:55 -0500 |
commit | 82b691bedf05f258f1c86c96ee574b0d7795c0a1 (patch) | |
tree | d97728fa77c736941fbcf7e0792f54bfe9bbf4c2 /kernel/softirq.c | |
parent | 6498ddad301c7a94162915d06d1efe2e5d20f6dc (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.c | 54 |
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 | } |
491 | EXPORT_SYMBOL(__tasklet_hi_schedule); | 491 | EXPORT_SYMBOL(__tasklet_hi_schedule); |
492 | 492 | ||
493 | static __latent_entropy void tasklet_action(struct softirq_action *a) | 493 | static 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 | ||
529 | static __latent_entropy void tasklet_hi_action(struct softirq_action *a) | 531 | static __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(); | 536 | static __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 | ||
565 | void tasklet_init(struct tasklet_struct *t, | 541 | void tasklet_init(struct tasklet_struct *t, |