There was a pure ->prio comparison left in try_to_wake_rt_mutex(),
convert it to use rt_mutex_waiter_less(), noting that greater-or-equal
is not-less (both in kernel priority view).

This necessitated the introduction of cmp_task() which creates a
pointer to an unnamed stack variable of struct rt_mutex_waiter type to
compare against tasks.

With this, we can now also create and employ rt_mutex_waiter_equal().

Reviewed-and-tested-by: Juri Lelli <juri.le...@arm.com>
Reviewed-by: Thomas Gleixner <t...@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <pet...@infradead.org>
---
 kernel/locking/rtmutex.c |   32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -158,6 +158,12 @@ static inline bool unlock_rt_mutex_safe(
 }
 #endif
 
+/*
+ * Only use with rt_mutex_waiter_{less,equal}()
+ */
+#define cmp_task(p)    \
+       &(struct rt_mutex_waiter){ .prio = (p)->prio, .deadline = 
(p)->dl.deadline }
+
 static inline int
 rt_mutex_waiter_less(struct rt_mutex_waiter *left,
                     struct rt_mutex_waiter *right)
@@ -177,6 +183,25 @@ rt_mutex_waiter_less(struct rt_mutex_wai
        return 0;
 }
 
+static inline int
+rt_mutex_waiter_equal(struct rt_mutex_waiter *left,
+                     struct rt_mutex_waiter *right)
+{
+       if (left->prio != right->prio)
+               return 0;
+
+       /*
+        * If both waiters have dl_prio(), we check the deadlines of the
+        * associated tasks.
+        * If left waiter has a dl_prio(), and we didn't return 0 above,
+        * then right waiter has a dl_prio() too.
+        */
+       if (dl_prio(left->prio))
+               return left->deadline == right->deadline;
+
+       return 1;
+}
+
 static void
 rt_mutex_enqueue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter)
 {
@@ -487,7 +512,7 @@ static int rt_mutex_adjust_prio_chain(st
         * enabled we continue, but stop the requeueing in the chain
         * walk.
         */
-       if (waiter->prio == task->prio && !dl_task(task)) {
+       if (rt_mutex_waiter_equal(waiter, cmp_task(task))) {
                if (!detect_deadlock)
                        goto out_unlock_pi;
                else
@@ -790,7 +815,8 @@ static int try_to_take_rt_mutex(struct r
                         * the top waiter priority (kernel view),
                         * @task lost.
                         */
-                       if (task->prio >= rt_mutex_top_waiter(lock)->prio)
+                       if (!rt_mutex_waiter_less(cmp_task(task),
+                                                 rt_mutex_top_waiter(lock)))
                                return 0;
 
                        /*
@@ -1055,7 +1081,7 @@ void rt_mutex_adjust_pi(struct task_stru
        raw_spin_lock_irqsave(&task->pi_lock, flags);
 
        waiter = task->pi_blocked_on;
-       if (!waiter || (waiter->prio == task->prio && !dl_prio(task->prio))) {
+       if (!waiter || rt_mutex_waiter_equal(waiter, cmp_task(task))) {
                raw_spin_unlock_irqrestore(&task->pi_lock, flags);
                return;
        }


Reply via email to