Skip to content

Commit bf7a281

Browse files
committed
Merge tag 'locking-urgent-2024-12-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull locking fix from Ingo Molnar: "Fix missed rtmutex wakeups causing sporadic boot hangs and other misbehavior" * tag 'locking-urgent-2024-12-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: locking/rtmutex: Make sure we wake anything on the wake_q when we release the lock->wait_lock
2 parents feffd35 + 4a07791 commit bf7a281

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

kernel/locking/rtmutex.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,13 @@ static int __sched task_blocks_on_rt_mutex(struct rt_mutex_base *lock,
12921292
*/
12931293
get_task_struct(owner);
12941294

1295+
preempt_disable();
12951296
raw_spin_unlock_irq(&lock->wait_lock);
1297+
/* wake up any tasks on the wake_q before calling rt_mutex_adjust_prio_chain */
1298+
wake_up_q(wake_q);
1299+
wake_q_init(wake_q);
1300+
preempt_enable();
1301+
12961302

12971303
res = rt_mutex_adjust_prio_chain(owner, chwalk, lock,
12981304
next_lock, waiter, task);
@@ -1596,14 +1602,16 @@ static void __sched remove_waiter(struct rt_mutex_base *lock,
15961602
* or TASK_UNINTERRUPTIBLE)
15971603
* @timeout: the pre-initialized and started timer, or NULL for none
15981604
* @waiter: the pre-initialized rt_mutex_waiter
1605+
* @wake_q: wake_q of tasks to wake when we drop the lock->wait_lock
15991606
*
16001607
* Must be called with lock->wait_lock held and interrupts disabled
16011608
*/
16021609
static int __sched rt_mutex_slowlock_block(struct rt_mutex_base *lock,
16031610
struct ww_acquire_ctx *ww_ctx,
16041611
unsigned int state,
16051612
struct hrtimer_sleeper *timeout,
1606-
struct rt_mutex_waiter *waiter)
1613+
struct rt_mutex_waiter *waiter,
1614+
struct wake_q_head *wake_q)
16071615
__releases(&lock->wait_lock) __acquires(&lock->wait_lock)
16081616
{
16091617
struct rt_mutex *rtm = container_of(lock, struct rt_mutex, rtmutex);
@@ -1634,7 +1642,13 @@ static int __sched rt_mutex_slowlock_block(struct rt_mutex_base *lock,
16341642
owner = rt_mutex_owner(lock);
16351643
else
16361644
owner = NULL;
1645+
preempt_disable();
16371646
raw_spin_unlock_irq(&lock->wait_lock);
1647+
if (wake_q) {
1648+
wake_up_q(wake_q);
1649+
wake_q_init(wake_q);
1650+
}
1651+
preempt_enable();
16381652

16391653
if (!owner || !rtmutex_spin_on_owner(lock, waiter, owner))
16401654
rt_mutex_schedule();
@@ -1708,7 +1722,7 @@ static int __sched __rt_mutex_slowlock(struct rt_mutex_base *lock,
17081722

17091723
ret = task_blocks_on_rt_mutex(lock, waiter, current, ww_ctx, chwalk, wake_q);
17101724
if (likely(!ret))
1711-
ret = rt_mutex_slowlock_block(lock, ww_ctx, state, NULL, waiter);
1725+
ret = rt_mutex_slowlock_block(lock, ww_ctx, state, NULL, waiter, wake_q);
17121726

17131727
if (likely(!ret)) {
17141728
/* acquired the lock */

kernel/locking/rtmutex_api.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ int __sched rt_mutex_wait_proxy_lock(struct rt_mutex_base *lock,
383383
raw_spin_lock_irq(&lock->wait_lock);
384384
/* sleep on the mutex */
385385
set_current_state(TASK_INTERRUPTIBLE);
386-
ret = rt_mutex_slowlock_block(lock, NULL, TASK_INTERRUPTIBLE, to, waiter);
386+
ret = rt_mutex_slowlock_block(lock, NULL, TASK_INTERRUPTIBLE, to, waiter, NULL);
387387
/*
388388
* try_to_take_rt_mutex() sets the waiter bit unconditionally. We might
389389
* have to fix that up.

0 commit comments

Comments
 (0)