diff options
Diffstat (limited to 'debian/patches-rt/0137-tasklets-Replace-spin-wait-in-tasklet_kill.patch')
-rw-r--r-- | debian/patches-rt/0137-tasklets-Replace-spin-wait-in-tasklet_kill.patch | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/debian/patches-rt/0137-tasklets-Replace-spin-wait-in-tasklet_kill.patch b/debian/patches-rt/0137-tasklets-Replace-spin-wait-in-tasklet_kill.patch new file mode 100644 index 000000000..619e62b2a --- /dev/null +++ b/debian/patches-rt/0137-tasklets-Replace-spin-wait-in-tasklet_kill.patch @@ -0,0 +1,74 @@ +From cc2fc16258410420e97a4873f760cffabcff49b0 Mon Sep 17 00:00:00 2001 +From: Peter Zijlstra <peterz@infradead.org> +Date: Tue, 9 Mar 2021 09:42:09 +0100 +Subject: [PATCH 137/323] tasklets: Replace spin wait in tasklet_kill() +Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/5.10/older/patches-5.10.204-rt100.tar.xz + +tasklet_kill() spin waits for TASKLET_STATE_SCHED to be cleared invoking +yield() from inside the loop. yield() is an ill defined mechanism and the +result might still be wasting CPU cycles in a tight loop which is +especially painful in a guest when the CPU running the tasklet is scheduled +out. + +tasklet_kill() is used in teardown paths and not performance critical at +all. Replace the spin wait with wait_var_event(). + +Signed-off-by: Peter Zijlstra <peterz@infradead.org> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + kernel/softirq.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/kernel/softirq.c b/kernel/softirq.c +index 06bca024ce45..ecc3ac4091c8 100644 +--- a/kernel/softirq.c ++++ b/kernel/softirq.c +@@ -530,6 +530,16 @@ void __tasklet_hi_schedule(struct tasklet_struct *t) + } + EXPORT_SYMBOL(__tasklet_hi_schedule); + ++static inline bool tasklet_clear_sched(struct tasklet_struct *t) ++{ ++ if (test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) { ++ wake_up_var(&t->state); ++ return true; ++ } ++ ++ return false; ++} ++ + static void tasklet_action_common(struct softirq_action *a, + struct tasklet_head *tl_head, + unsigned int softirq_nr) +@@ -549,8 +559,7 @@ static void tasklet_action_common(struct softirq_action *a, + + if (tasklet_trylock(t)) { + if (!atomic_read(&t->count)) { +- if (!test_and_clear_bit(TASKLET_STATE_SCHED, +- &t->state)) ++ if (!tasklet_clear_sched(t)) + BUG(); + if (t->use_callback) + t->callback(t); +@@ -610,13 +619,11 @@ void tasklet_kill(struct tasklet_struct *t) + if (in_interrupt()) + pr_notice("Attempt to kill tasklet from interrupt\n"); + +- while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) { +- do { +- yield(); +- } while (test_bit(TASKLET_STATE_SCHED, &t->state)); +- } ++ while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) ++ wait_var_event(&t->state, !test_bit(TASKLET_STATE_SCHED, &t->state)); ++ + tasklet_unlock_wait(t); +- clear_bit(TASKLET_STATE_SCHED, &t->state); ++ tasklet_clear_sched(t); + } + EXPORT_SYMBOL(tasklet_kill); + +-- +2.43.0 + |