Re: [PATCH 1/5] locking/rtmutex: Stop spinning on the owner when the waiter is woken
From: Mathieu Desnoyers
Date: Sat Nov 07 2026 - 14:40:10 EST
On 2026-11-07 12:36, Steven Rostedt wrote:
[...]
Still way too verbose for the fix. It makes it sound more complicatedIt drops important information, such as the user visible impact of the
than it is.
locking/rtmutex: Stop spinning on the owner when the waiter is woken
The top waiter of an rt_mutex sets its sleep state. Then it spins in
rtmutex_spin_on_owner() as long as the owner is running. A wakeup sets
the waiter back to TASK_RUNNING. The spin loop does not check for this.
So a timeout or a signal is only handled when the owner blocks, or when
the waiter has to reschedule.
The rtmutex_spin_on_owner() is just an optimization with the idea that
if the owner is still running on a CPU, it will likely release it soon.
If the owner gets preempted or schedules out on its own, the spinning
will stop and the waiter will sleep. This came from PREEMPT_RT adaptive
spinning for rt_spin_locks that allowed them to behave more like normal
spin locks and speed up PREEMPT_RT performance.
The problem is that when this was implemented for futex and normal
mutexes it did not account for timeouts or other mechanisms where
the owner releasing the lock wasn't the only way for the spinning
task to exit the mutex acquire. The spinning currently does not
account for anything else but the lock being released or the owner
sleeping.
Luckily, when the spinning task needs to exit the mutex lock code, it's
state is set to TASK_RUNNING. By having the spin check the spinning
task's state to see if it switches to running, it can exit the spin
appropriately.
How about something like the above?
issue. How about this remix ?
locking/rtmutex: Stop spinning on the owner when the waiter is woken
The top waiter of an rt_mutex sets its sleep state. Then it spins in
rtmutex_spin_on_owner() as long as the owner is running. A wakeup sets
the waiter back to TASK_RUNNING. The spin loop does not check for this.
So a timeout or a signal is only handled when the owner blocks, or when
the waiter has to reschedule.
The spin is an optimization. A running owner will likely release the
lock soon, so the waiter spins instead of going to sleep. It comes
from the PREEMPT_RT adaptive spinning for rt_spin_locks. Only the
lock handoff wakes an rt_spin_lock waiter, so the spin did not need to
check for other wakeups there. The spin was then extended to all
rtmutex based locks. Their waiters can also be woken by a timeout, a
signal or a ww_mutex wound.
The owner of a PI futex is a user task. It can run for a long time.
With an owner spinning in userspace, a 1ms pthread_mutex_timedlock()
returned up to 1.4s late in testing. A signal to the waiter is delayed
too.
With PREEMPT_RT, two contexts that take two ww_mutexes in opposite
order spin on each other. Only something else that needs one of the two
CPUs stops them. By default, the fair server does it after 950ms, to
run SCHED_OTHER tasks.
Fix this by also stopping the spin when the waiter is TASK_RUNNING. The
slowpath then handles the wakeup, as it does after schedule().
PI mutex throughput is unchanged. The futex and ww_mutex selftests added
later in this series test both cases.
Fixes: 992caf7f1724 ("locking/rtmutex: Add adaptive spinwait mechanism")
Cc: stable@xxxxxxxxxxxxxxx
Reviewed-by: Steven Rostedt <rostedt@xxxxxxxxxxx>
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@xxxxxxxxxxxx>
Thanks,
Mathieu
--
Mathieu Desnoyers
EfficiOS Inc.
https://www.efficios.com