linux/debian/patches-rt/0328-tasklet-Fix-UP-case-fo...

60 lines
2.2 KiB
Diff

From 9e4127f120a46693ef293d65465523daab444e57 Mon Sep 17 00:00:00 2001
Message-Id: <9e4127f120a46693ef293d65465523daab444e57.1601675153.git.zanussi@kernel.org>
In-Reply-To: <5b5a156f9808b1acf1205606e03da117214549ea.1601675151.git.zanussi@kernel.org>
References: <5b5a156f9808b1acf1205606e03da117214549ea.1601675151.git.zanussi@kernel.org>
From: Tom Zanussi <zanussi@kernel.org>
Date: Tue, 9 Jun 2020 11:04:08 -0500
Subject: [PATCH 328/333] tasklet: Fix UP case for tasklet CHAINED state
Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.148-rt64.tar.xz
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:
*/
--
2.17.1