|
@@ -314,7 +314,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
|
|
|
}
|
|
|
put_task_struct(task);
|
|
|
|
|
|
- return deadlock_detect ? -EDEADLK : 0;
|
|
|
+ return -EDEADLK;
|
|
|
}
|
|
|
retry:
|
|
|
/*
|
|
@@ -377,7 +377,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
|
|
|
if (lock == orig_lock || rt_mutex_owner(lock) == top_task) {
|
|
|
debug_rt_mutex_deadlock(deadlock_detect, orig_waiter, lock);
|
|
|
raw_spin_unlock(&lock->wait_lock);
|
|
|
- ret = deadlock_detect ? -EDEADLK : 0;
|
|
|
+ ret = -EDEADLK;
|
|
|
goto out_unlock_pi;
|
|
|
}
|
|
|
|
|
@@ -548,7 +548,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
|
|
|
* which is wrong, as the other waiter is not in a deadlock
|
|
|
* situation.
|
|
|
*/
|
|
|
- if (detect_deadlock && owner == task)
|
|
|
+ if (owner == task)
|
|
|
return -EDEADLK;
|
|
|
|
|
|
raw_spin_lock_irqsave(&task->pi_lock, flags);
|
|
@@ -763,6 +763,26 @@ __rt_mutex_slowlock(struct rt_mutex *lock, int state,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static void rt_mutex_handle_deadlock(int res, int detect_deadlock,
|
|
|
+ struct rt_mutex_waiter *w)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * If the result is not -EDEADLOCK or the caller requested
|
|
|
+ * deadlock detection, nothing to do here.
|
|
|
+ */
|
|
|
+ if (res != -EDEADLOCK || detect_deadlock)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Yell lowdly and stop the task right here.
|
|
|
+ */
|
|
|
+ rt_mutex_print_deadlock(w);
|
|
|
+ while (1) {
|
|
|
+ set_current_state(TASK_INTERRUPTIBLE);
|
|
|
+ schedule();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Slow path lock function:
|
|
|
*/
|
|
@@ -802,8 +822,10 @@ rt_mutex_slowlock(struct rt_mutex *lock, int state,
|
|
|
|
|
|
set_current_state(TASK_RUNNING);
|
|
|
|
|
|
- if (unlikely(ret))
|
|
|
+ if (unlikely(ret)) {
|
|
|
remove_waiter(lock, &waiter);
|
|
|
+ rt_mutex_handle_deadlock(ret, detect_deadlock, &waiter);
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
|
* try_to_take_rt_mutex() sets the waiter bit
|
|
@@ -1112,7 +1134,8 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
- ret = task_blocks_on_rt_mutex(lock, waiter, task, detect_deadlock);
|
|
|
+ /* We enforce deadlock detection for futexes */
|
|
|
+ ret = task_blocks_on_rt_mutex(lock, waiter, task, 1);
|
|
|
|
|
|
if (ret && !rt_mutex_owner(lock)) {
|
|
|
/*
|