summaryrefslogtreecommitdiffstats
path: root/debian/patches-rt/0327-tasklet-Fix-UP-case-for-tasklet-CHAINED-state.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches-rt/0327-tasklet-Fix-UP-case-for-tasklet-CHAINED-state.patch')
-rw-r--r--debian/patches-rt/0327-tasklet-Fix-UP-case-for-tasklet-CHAINED-state.patch52
1 files changed, 52 insertions, 0 deletions
diff --git a/debian/patches-rt/0327-tasklet-Fix-UP-case-for-tasklet-CHAINED-state.patch b/debian/patches-rt/0327-tasklet-Fix-UP-case-for-tasklet-CHAINED-state.patch
new file mode 100644
index 000000000..448ee797a
--- /dev/null
+++ b/debian/patches-rt/0327-tasklet-Fix-UP-case-for-tasklet-CHAINED-state.patch
@@ -0,0 +1,52 @@
+From: Tom Zanussi <zanussi@kernel.org>
+Date: Tue, 9 Jun 2020 11:04:08 -0500
+Subject: [PATCH 327/342] tasklet: Fix UP case for tasklet CHAINED state
+Origin: https://git.kernel.org/cgit/linux/kernel/git/rt/linux-stable-rt.git/commit?id=ca828148bcc43ec7ed745e6bb0c076441138f09f
+
+commit 62d0a2a30cd0 (tasklet: Address a race resulting in
+double-enqueue) addresses a problem that can result in a tasklet being
+enqueued on two cpus at the same time by combining the RUN flag with a
+new CHAINED flag, and relies on the combination to be present in order
+to zero it out, which can never happen on (!SMP and !PREEMPT_RT_FULL)
+because the RUN flag is SMP/PREEMPT_RT_FULL-only.
+
+So make sure the above commit is only applied for the SMP ||
+PREEMPT_RT_FULL case.
+
+Fixes: 62d0a2a30cd0 ("tasklet: Address a race resulting in double-enqueue")
+Signed-off-by: Tom Zanussi <zanussi@kernel.org>
+Reported-by: Ramon Fried <rfried.dev@gmail.com>
+Tested-By: Ramon Fried <rfried.dev@gmail.com>
+---
+ kernel/softirq.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/kernel/softirq.c b/kernel/softirq.c
+index 73dae64bfc9c..9bad7a16dc61 100644
+--- a/kernel/softirq.c
++++ b/kernel/softirq.c
+@@ -947,10 +947,12 @@ static void __tasklet_schedule_common(struct tasklet_struct *t,
+ * is locked before adding it to the list.
+ */
+ if (test_bit(TASKLET_STATE_SCHED, &t->state)) {
++#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT_FULL)
+ if (test_and_set_bit(TASKLET_STATE_CHAINED, &t->state)) {
+ tasklet_unlock(t);
+ return;
+ }
++#endif
+ t->next = NULL;
+ *head->tail = t;
+ head->tail = &(t->next);
+@@ -1044,7 +1046,11 @@ static void tasklet_action_common(struct softirq_action *a,
+ again:
+ t->func(t->data);
+
++#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT_FULL)
+ while (cmpxchg(&t->state, TASKLET_STATEF_RC, 0) != TASKLET_STATEF_RC) {
++#else
++ while (!tasklet_tryunlock(t)) {
++#endif
+ /*
+ * If it got disabled meanwhile, bail out:
+ */