60 lines
2.2 KiB
Diff
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
|
|
|