|
@@ -238,8 +238,7 @@ rt_mutex_waiter_less(struct rt_mutex_waiter *left,
|
|
|
* then right waiter has a dl_prio() too.
|
|
|
*/
|
|
|
if (dl_prio(left->prio))
|
|
|
- return dl_time_before(left->task->dl.deadline,
|
|
|
- right->task->dl.deadline);
|
|
|
+ return dl_time_before(left->deadline, right->deadline);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -650,7 +649,26 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
|
|
|
|
|
|
/* [7] Requeue the waiter in the lock waiter tree. */
|
|
|
rt_mutex_dequeue(lock, waiter);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Update the waiter prio fields now that we're dequeued.
|
|
|
+ *
|
|
|
+ * These values can have changed through either:
|
|
|
+ *
|
|
|
+ * sys_sched_set_scheduler() / sys_sched_setattr()
|
|
|
+ *
|
|
|
+ * or
|
|
|
+ *
|
|
|
+ * DL CBS enforcement advancing the effective deadline.
|
|
|
+ *
|
|
|
+ * Even though pi_waiters also uses these fields, and that tree is only
|
|
|
+ * updated in [11], we can do this here, since we hold [L], which
|
|
|
+ * serializes all pi_waiters access and rb_erase() does not care about
|
|
|
+ * the values of the node being removed.
|
|
|
+ */
|
|
|
waiter->prio = task->prio;
|
|
|
+ waiter->deadline = task->dl.deadline;
|
|
|
+
|
|
|
rt_mutex_enqueue(lock, waiter);
|
|
|
|
|
|
/* [8] Release the task */
|
|
@@ -777,6 +795,8 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
|
|
|
static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task,
|
|
|
struct rt_mutex_waiter *waiter)
|
|
|
{
|
|
|
+ lockdep_assert_held(&lock->wait_lock);
|
|
|
+
|
|
|
/*
|
|
|
* Before testing whether we can acquire @lock, we set the
|
|
|
* RT_MUTEX_HAS_WAITERS bit in @lock->owner. This forces all
|
|
@@ -902,6 +922,8 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
|
|
|
struct rt_mutex *next_lock;
|
|
|
int chain_walk = 0, res;
|
|
|
|
|
|
+ lockdep_assert_held(&lock->wait_lock);
|
|
|
+
|
|
|
/*
|
|
|
* Early deadlock detection. We really don't want the task to
|
|
|
* enqueue on itself just to untangle the mess later. It's not
|
|
@@ -919,6 +941,7 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
|
|
|
waiter->task = task;
|
|
|
waiter->lock = lock;
|
|
|
waiter->prio = task->prio;
|
|
|
+ waiter->deadline = task->dl.deadline;
|
|
|
|
|
|
/* Get the top priority waiter on the lock */
|
|
|
if (rt_mutex_has_waiters(lock))
|
|
@@ -1036,6 +1059,8 @@ static void remove_waiter(struct rt_mutex *lock,
|
|
|
struct task_struct *owner = rt_mutex_owner(lock);
|
|
|
struct rt_mutex *next_lock;
|
|
|
|
|
|
+ lockdep_assert_held(&lock->wait_lock);
|
|
|
+
|
|
|
raw_spin_lock(¤t->pi_lock);
|
|
|
rt_mutex_dequeue(lock, waiter);
|
|
|
current->pi_blocked_on = NULL;
|