diff options
author | Peter Zijlstra <peterz@infradead.org> | 2017-03-23 10:56:14 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2017-04-04 05:44:07 -0400 |
commit | 19830e55247cddb3f46f1bf60b8e245593491bea (patch) | |
tree | cd0995361901d81ef37e13f24d894a990f5f471b /kernel/locking/rtmutex.c | |
parent | e0aad5b44ff5d28ac1d6ae70cdf84ca228e889dc (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.c | 32 |
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 | |||
227 | static inline int | 233 | static inline int |
228 | rt_mutex_waiter_less(struct rt_mutex_waiter *left, | 234 | rt_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 | ||
252 | static inline int | ||
253 | rt_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 | |||
246 | static void | 271 | static void |
247 | rt_mutex_enqueue(struct rt_mutex *lock, struct rt_mutex_waiter *waiter) | 272 | rt_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 | } |