From: Peter Zijlstra <peterz@infradead.org>
To: John Stultz <jstultz@google.com>
Cc: LKML <linux-kernel@vger.kernel.org>,
Ingo Molnar <mingo@redhat.com>, Will Deacon <will@kernel.org>,
Waiman Long <longman@redhat.com>,
Boqun Feng <boqun.feng@gmail.com>,
Thomas Gleixner <tglx@linutronix.de>,
Bert Karwatzki <spasswolf@web.de>,
kernel-team@android.com
Subject: Re: [RFC][PATCH] locking/rtmutex: Make sure we wake anything on the wake_q when we release the lock->wait_lock
Date: Fri, 13 Dec 2024 13:46:14 +0100 [thread overview]
Message-ID: <20241213124614.GA12338@noisy.programming.kicks-ass.net> (raw)
In-Reply-To: <20241212222138.2400498-1-jstultz@google.com>
On Thu, Dec 12, 2024 at 02:21:33PM -0800, John Stultz wrote:
> Bert reported seeing occasional boot hangs when running with
> PREEPT_RT and bisected it down to commit 894d1b3db41c
> ("locking/mutex: Remove wakeups from under mutex::wait_lock").
>
> It looks like I missed a few spots where we drop the wait_lock and
> potentially call into schedule without waking up the tasks on the
> wake_q structure. Since the tasks being woken are ww_mutex tasks
> they need to be able to run to release the mutex and unblock the
> task that currently is planning to wake them. Thus we can deadlock.
>
> So make sure we wake the wake_q tasks when we unlock the wait_lock.
>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Waiman Long <longman@redhat.com>
> Cc: Boqun Feng <boqun.feng@gmail.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Bert Karwatzki <spasswolf@web.de>
> Cc: kernel-team@android.com
> Reported-by: Bert Karwatzki <spasswolf@web.de>
> Closes: https://lore.kernel.org/lkml/20241211182502.2915-1-spasswolf@web.de
> Fixes: 894d1b3db41c ("locking/mutex: Remove wakeups from under mutex::wait_lock")
> Signed-off-by: John Stultz <jstultz@google.com>
> ---
I don't suppose this actually makes things much better -- but I had to
try.
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1192,6 +1192,17 @@ try_to_take_rt_mutex(struct rt_mutex_bas
return 1;
}
+#define WRAP_WAKE(_stmt, _q) \
+do { \
+ struct wake_q_head *_Q = (_q); \
+ guard(preempt)(); \
+ _stmt; \
+ if (_Q && !wake_q_empty(_Q)) { \
+ wake_up_q(_Q); \
+ wake_q_init(_Q); \
+ } \
+} while (0)
+
/*
* Task blocks on lock.
*
@@ -1248,10 +1259,7 @@ static int __sched task_blocks_on_rt_mut
/* Check whether the waiter should back out immediately */
rtm = container_of(lock, struct rt_mutex, rtmutex);
- preempt_disable();
- res = __ww_mutex_add_waiter(waiter, rtm, ww_ctx, wake_q);
- wake_up_q(wake_q);
- preempt_enable();
+ WRAP_WAKE(res = __ww_mutex_add_waiter(waiter, rtm, ww_ctx, wake_q), wake_q);
if (res) {
raw_spin_lock(&task->pi_lock);
rt_mutex_dequeue(lock, waiter);
@@ -1295,13 +1303,7 @@ static int __sched task_blocks_on_rt_mut
*/
get_task_struct(owner);
- preempt_disable();
- raw_spin_unlock_irq(&lock->wait_lock);
- /* wake up any tasks on the wake_q before calling rt_mutex_adjust_prio_chain */
- wake_up_q(wake_q);
- wake_q_init(wake_q);
- preempt_enable();
-
+ WRAP_WAKE(raw_spin_unlock_irq(&lock->wait_lock), wake_q);
res = rt_mutex_adjust_prio_chain(owner, chwalk, lock,
next_lock, waiter, task);
@@ -1645,13 +1647,8 @@ static int __sched rt_mutex_slowlock_blo
owner = rt_mutex_owner(lock);
else
owner = NULL;
- preempt_disable();
- raw_spin_unlock_irq(&lock->wait_lock);
- if (wake_q) {
- wake_up_q(wake_q);
- wake_q_init(wake_q);
- }
- preempt_enable();
+
+ WRAP_WAKE(raw_spin_unlock_irq(&lock->wait_lock), wake_q);
if (!owner || !rtmutex_spin_on_owner(lock, waiter, owner))
rt_mutex_schedule();
@@ -1802,10 +1799,7 @@ static int __sched rt_mutex_slowlock(str
*/
raw_spin_lock_irqsave(&lock->wait_lock, flags);
ret = __rt_mutex_slowlock_locked(lock, ww_ctx, state, &wake_q);
- preempt_disable();
- raw_spin_unlock_irqrestore(&lock->wait_lock, flags);
- wake_up_q(&wake_q);
- preempt_enable();
+ WRAP_WAKE(raw_spin_unlock_irqrestore(&lock->wait_lock, flags), &wake_q);
rt_mutex_post_schedule();
return ret;
@@ -1863,11 +1857,8 @@ static void __sched rtlock_slowlock_lock
owner = rt_mutex_owner(lock);
else
owner = NULL;
- preempt_disable();
- raw_spin_unlock_irq(&lock->wait_lock);
- wake_up_q(wake_q);
- wake_q_init(wake_q);
- preempt_enable();
+
+ WRAP_WAKE(raw_spin_unlock_irq(&lock->wait_lock), wake_q);
if (!owner || !rtmutex_spin_on_owner(lock, &waiter, owner))
schedule_rtlock();
@@ -1896,10 +1887,8 @@ static __always_inline void __sched rtlo
raw_spin_lock_irqsave(&lock->wait_lock, flags);
rtlock_slowlock_locked(lock, &wake_q);
- preempt_disable();
- raw_spin_unlock_irqrestore(&lock->wait_lock, flags);
- wake_up_q(&wake_q);
- preempt_enable();
+
+ WRAP_WAKE(raw_spin_unlock_irqrestore(&lock->wait_lock, flags), &wake_q);
}
#endif /* RT_MUTEX_BUILD_SPINLOCKS */
next prev parent reply other threads:[~2024-12-13 12:46 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-12 22:21 [RFC][PATCH] locking/rtmutex: Make sure we wake anything on the wake_q when we release the lock->wait_lock John Stultz
2024-12-13 12:46 ` Peter Zijlstra [this message]
2024-12-13 13:59 ` Peter Zijlstra
2024-12-14 2:39 ` John Stultz
2024-12-14 18:46 ` Peter Zijlstra
2024-12-17 4:07 ` [RFC][PATCH] sched/wake_q: Add helper to call wake_up_q after unlock with preemption disabled John Stultz
2024-12-24 18:53 ` [tip: locking/core] " tip-bot2 for John Stultz
2024-12-24 9:46 ` [tip: locking/urgent] locking/rtmutex: Make sure we wake anything on the wake_q when we release the lock->wait_lock tip-bot2 for John Stultz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241213124614.GA12338@noisy.programming.kicks-ass.net \
--to=peterz@infradead.org \
--cc=boqun.feng@gmail.com \
--cc=jstultz@google.com \
--cc=kernel-team@android.com \
--cc=linux-kernel@vger.kernel.org \
--cc=longman@redhat.com \
--cc=mingo@redhat.com \
--cc=spasswolf@web.de \
--cc=tglx@linutronix.de \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.