Fixed
Created: Sep 6, 2016
Updated: Dec 3, 2018
Resolved Date: Sep 22, 2016
Found In Version: 6.0.0.27
Fix Version: 6.0.0.31
Severity: Standard
Applicable for: Wind River Linux 6
Component/s: Kernel
I found a problem related to rtmutex which may introduce a deadlock.
The problem is in wakeup_next_waiter() as follows:
static void wakeup_next_waiter(struct rt_mutex *lock)
{
...
rt_mutex_wake_waiter(waiter);
wake_up_process(waiter->task);
}
I think last calling of wake_up_process() is not necessary because waiter->task is already woken up in rt_mutex_wake_waiter(). To make matters worse, I think the calling of wake_up_process() may introduce a deadlock. The scenario of the deadlock is as follows:
CPU0 CPU1
====================================================================================================
rt_spin_lock_slowlock
schedule_rt_mutex(lock);
<sleeping...>
rt_spin_lock_slowunlock
raw_spin_lock(&lock->wait_lock)
__rt_spin_lock_slowunlock(lock)
wakeup_next_waiter(lock)
...
rt_mutex_wake_waiter(waiter);
wake_up_lock_sleeper(waiter->task);
try_to_wake_up(p, TASK_ALL,
WF_LOCK_SLEEPER);
...
while (p->on_cpu)
cpu_relax();
...
ttwu_queue(p, cpu); -----------------------> <waked up>
raw_spin_lock(&lock->wait_lock);
<spinning...>
wake_up_process(waiter->task);
try_to_wake_up(p, TASK_NORMAL, 0);
while (p->on_cpu)
cpu_relax();
<spinning>
raw_spin_unlock(&lock->wait_lock);
In upstream linux-rt-devel tree, there is no calling of last wake_up_process() in wakeup_next_waiter().
Please check it, and let me know if my understanding is wrong.