aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/locking/rtmutex.c
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2017-03-23 10:56:14 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-04-04 05:44:07 -0400
commit19830e55247cddb3f46f1bf60b8e245593491bea (patch)
treecd0995361901d81ef37e13f24d894a990f5f471b /kernel/locking/rtmutex.c
parente0aad5b44ff5d28ac1d6ae70cdf84ca228e889dc (diff)
rtmutex: Fix more prio comparisons
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.lelli@arm.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Cc: juri.lelli@arm.com Cc: bigeasy@linutronix.de Cc: xlpang@redhat.com Cc: rostedt@goodmis.org Cc: mathieu.desnoyers@efficios.com Cc: jdesfossez@efficios.com Cc: bristot@redhat.com Link: http://lkml.kernel.org/r/20170323150216.455584638@infradead.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/locking/rtmutex.c')
-rw-r--r--kernel/locking/rtmutex.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index c6eda049ef9f..0e641eb473de 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -224,6 +224,12 @@ static inline bool unlock_rt_mutex_safe(struct rt_mutex *lock,
224} 224}
225#endif 225#endif
226 226
227/*
228 * Only use with rt_mutex_waiter_{less,equal}()
229 */
230#define task_to_waiter(p) \
231 &(struct rt_mutex_waiter){ .prio = (p)->prio, .deadline = (p)->dl.deadline }
232
227static inline int 233static inline int
228rt_mutex_waiter_less(struct rt_mutex_waiter *left, 234rt_mutex_waiter_less(struct rt_mutex_waiter *left,
229 struct rt_mutex_waiter *right) 235 struct rt_mutex_waiter *right)
@@ -243,6 +249,25 @@ rt_mutex_waiter_less(struct rt_mutex_waiter *left,
243 return 0; 249 return 0;
244} 250}
245 251
252static inline int
253rt_mutex_waiter_equal(struct rt_mutex_waiter *left,
254 struct rt_mutex_waiter *right)
255{
256 if (left->prio != right->prio)
257 return 0;
258
259 /*
260 * If both waiters have dl_prio(), we check the deadlines of the
261 * associated tasks.
262 * If left waiter has a dl_prio(), and we didn't return 0 above,
263 * then right waiter has a dl_prio() too.
264 */
265 if (dl_prio(left->prio))
266 return left->deadline == right->deadline;
267
268 return 1;
269}
270
246static void 271static void
247rt_mutex_enqueue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter) 272rt_mutex_enqueue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter)
248{ 273{
@@ -553,7 +578,7 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
553 * enabled we continue, but stop the requeueing in the chain 578 * enabled we continue, but stop the requeueing in the chain
554 * walk. 579 * walk.
555 */ 580 */
556 if (waiter->prio == task->prio && !dl_task(task)) { 581 if (rt_mutex_waiter_equal(waiter, task_to_waiter(task))) {
557 if (!detect_deadlock) 582 if (!detect_deadlock)
558 goto out_unlock_pi; 583 goto out_unlock_pi;
559 else 584 else
@@ -856,7 +881,8 @@ static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task,
856 * the top waiter priority (kernel view), 881 * the top waiter priority (kernel view),
857 * @task lost. 882 * @task lost.
858 */ 883 */
859 if (task->prio >= rt_mutex_top_waiter(lock)->prio) 884 if (!rt_mutex_waiter_less(task_to_waiter(task),
885 rt_mutex_top_waiter(lock)))
860 return 0; 886 return 0;
861 887
862 /* 888 /*
@@ -1119,7 +1145,7 @@ void rt_mutex_adjust_pi(struct task_struct *task)
1119 raw_spin_lock_irqsave(&task->pi_lock, flags); 1145 raw_spin_lock_irqsave(&task->pi_lock, flags);
1120 1146
1121 waiter = task->pi_blocked_on; 1147 waiter = task->pi_blocked_on;
1122 if (!waiter || (waiter->prio == task->prio && !dl_prio(task->prio))) { 1148 if (!waiter || rt_mutex_waiter_equal(waiter, task_to_waiter(task))) {
1123 raw_spin_unlock_irqrestore(&task->pi_lock, flags); 1149 raw_spin_unlock_irqrestore(&task->pi_lock, flags);
1124 return; 1150 return;
1125 } 1151 }