diff --git a/kernel/rtmutex.c b/kernel/rtmutex.c index 6131a046aab64..520d0e2ed4088 100644 --- a/kernel/rtmutex.c +++ b/kernel/rtmutex.c @@ -604,19 +604,25 @@ static void mark_wakeup_next_waiter(struct wake_q_head *wake_q, * * Must be called with lock->wait_lock held and * have just failed to try_to_take_rt_mutex(). + * + * When invoked from rt_mutex_start_proxy_lock() waiter::task != current ! */ static void remove_waiter(struct rt_mutex *lock, struct rt_mutex_waiter *waiter) { int first = (waiter == rt_mutex_top_waiter(lock)); struct task_struct *owner = rt_mutex_owner(lock); + struct task_struct *waiter_task = waiter->task; unsigned long flags; int chain_walk = 0; - raw_spin_lock_irqsave(¤t->pi_lock, flags); + if (!waiter_task) /* never enqueued */ + return; + + raw_spin_lock_irqsave(&waiter_task->pi_lock, flags); rt_mutex_dequeue(lock, waiter); - current->pi_blocked_on = NULL; - raw_spin_unlock_irqrestore(¤t->pi_lock, flags); + waiter_task->pi_blocked_on = NULL; + raw_spin_unlock_irqrestore(&waiter_task->pi_lock, flags); if (!owner) return; @@ -649,7 +655,7 @@ static void remove_waiter(struct rt_mutex *lock, raw_spin_unlock(&lock->wait_lock); - rt_mutex_adjust_prio_chain(owner, 0, lock, NULL, current); + rt_mutex_adjust_prio_chain(owner, 0, lock, NULL, waiter_task); raw_spin_lock(&lock->wait_lock); } @@ -1093,7 +1099,7 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock, ret = 0; } - if (unlikely(ret)) + if (unlikely(ret < 0)) remove_waiter(lock, waiter); raw_spin_unlock(&lock->wait_lock);