[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250826110833.3274209-1-cuiguoqi@kylinos.cn>
Date: Tue, 26 Aug 2025 19:08:33 +0800
From: cuiguoqi <cuiguoqi@...inos.cn>
To: Ingo Molnar <mingo@...hat.com>,
Peter Zijlstra <peterz@...radead.org>,
Juri Lelli <juri.lelli@...hat.com>,
Vincent Guittot <vincent.guittot@...aro.org>
Cc: Dietmar Eggemann <dietmar.eggemann@....com>,
Steven Rostedt <rostedt@...dmis.org>,
Ben Segall <bsegall@...gle.com>,
Mel Gorman <mgorman@...e.de>,
Valentin Schneider <vschneid@...hat.com>,
Sebastian Andrzej Siewior <bigeasy@...utronix.de>,
Clark Williams <clrkwllms@...nel.org>,
guoqi0226@....com,
linux-kernel@...r.kernel.org,
linux-rt-devel@...ts.linux.dev,
cuiguoqi <cuiguoqi@...inos.cn>
Subject: [PATCH] sched: Fix race in rt_mutex_pre_schedule by removing non-atomic fetch_and_set
During Wound/Wait testing on PREEMPT_RT, a WARNING was hit:
WARNING: CPU: 0 PID: 0 at kernel/sched/core.c:7085 rt_mutex_pre_schedule+0xa8/0x108
Call trace:
rt_mutex_pre_schedule+0xa8/0x108
__ww_rt_mutex_lock+0x1d4/0x300
ww_mutex_lock+0x1c/0x30
The issue stems from the non-atomic `fetch_and_set` macro:
#define fetch_and_set(x, v) ({ int _x = (x); (x) = (v); _x; })
It lacks atomicity and memory ordering, leading to race conditions under
preemption or interrupts, where `current->sched_rt_mutex` may be corrupted.
Since this flag is only used for lockdep assertions and accessed per-task,
replace the unsafe macro with direct assignment and explicit state checks:
- In rt_mutex_pre_schedule(): assert is 0 before setting to 1.
- In rt_mutex_post_schedule(): assert is 1 before clearing to 0.
This fixes the false-positive warning without needing atomic operations.
Signed-off-by: cuiguoqi <cuiguoqi@...inos.cn>
---
kernel/sched/core.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 5e89a6eeadba..fb4c446e46f7 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -7078,11 +7078,11 @@ const struct sched_class *__setscheduler_class(struct task_struct *p, int prio)
* name such that if someone were to implement this function we get to compare
* notes.
*/
-#define fetch_and_set(x, v) ({ int _x = (x); (x) = (v); _x; })
void rt_mutex_pre_schedule(void)
{
- lockdep_assert(!fetch_and_set(current->sched_rt_mutex, 1));
+ lockdep_assert(!current->sched_rt_mutex);
+ current->sched_rt_mutex = 1;
sched_submit_work(current);
}
@@ -7095,7 +7095,9 @@ void rt_mutex_schedule(void)
void rt_mutex_post_schedule(void)
{
sched_update_worker(current);
- lockdep_assert(fetch_and_set(current->sched_rt_mutex, 0));
+ lockdep_assert(current->sched_rt_mutex);
+ current->sched_rt_mutex = 0;
+
}
/*
--
2.25.1
Powered by blists - more mailing lists