aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/locking/rtmutex.c
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2017-03-23 10:56:13 -0400
committerThomas Gleixner <tglx@linutronix.de>2017-04-04 05:44:06 -0400
commite0aad5b44ff5d28ac1d6ae70cdf84ca228e889dc (patch)
tree5e15c53d3b2fa6096e14073a3f0140ca81aeeda4 /kernel/locking/rtmutex.c
parentb91473ff6e979c0028f02f90e40c844959c736d8 (diff)
rtmutex: Fix PI chain order integrity
rt_mutex_waiter::prio is a copy of task_struct::prio which is updated during the PI chain walk, such that the PI chain order isn't messed up by (asynchronous) task state updates. Currently rt_mutex_waiter_less() uses task state for deadline tasks; this is broken, since the task state can, as said above, change asynchronously, causing the RB tree order to change without actual tree update -> FAIL. Fix this by also copying the deadline into the rt_mutex_waiter state and updating it along with its prio field. Ideally we would also force PI chain updates whenever DL tasks update their deadline parameter, but for first approximation this is less broken than it was. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> 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.403992539@infradead.org Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/locking/rtmutex.c')
-rw-r--r--kernel/locking/rtmutex.c29
1 files changed, 27 insertions, 2 deletions
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 00b49cdbb4e0..c6eda049ef9f 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -238,8 +238,7 @@ rt_mutex_waiter_less(struct rt_mutex_waiter *left,
238 * then right waiter has a dl_prio() too. 238 * then right waiter has a dl_prio() too.
239 */ 239 */
240 if (dl_prio(left->prio)) 240 if (dl_prio(left->prio))
241 return dl_time_before(left->task->dl.deadline, 241 return dl_time_before(left->deadline, right->deadline);
242 right->task->dl.deadline);
243 242
244 return 0; 243 return 0;
245} 244}
@@ -650,7 +649,26 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
650 649
651 /* [7] Requeue the waiter in the lock waiter tree. */ 650 /* [7] Requeue the waiter in the lock waiter tree. */
652 rt_mutex_dequeue(lock, waiter); 651 rt_mutex_dequeue(lock, waiter);
652
653 /*
654 * Update the waiter prio fields now that we're dequeued.
655 *
656 * These values can have changed through either:
657 *
658 * sys_sched_set_scheduler() / sys_sched_setattr()
659 *
660 * or
661 *
662 * DL CBS enforcement advancing the effective deadline.
663 *
664 * Even though pi_waiters also uses these fields, and that tree is only
665 * updated in [11], we can do this here, since we hold [L], which
666 * serializes all pi_waiters access and rb_erase() does not care about
667 * the values of the node being removed.
668 */
653 waiter->prio = task->prio; 669 waiter->prio = task->prio;
670 waiter->deadline = task->dl.deadline;
671
654 rt_mutex_enqueue(lock, waiter); 672 rt_mutex_enqueue(lock, waiter);
655 673
656 /* [8] Release the task */ 674 /* [8] Release the task */
@@ -777,6 +795,8 @@ static int rt_mutex_adjust_prio_chain(struct task_struct *task,
777static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task, 795static int try_to_take_rt_mutex(struct rt_mutex *lock, struct task_struct *task,
778 struct rt_mutex_waiter *waiter) 796 struct rt_mutex_waiter *waiter)
779{ 797{
798 lockdep_assert_held(&lock->wait_lock);
799
780 /* 800 /*
781 * Before testing whether we can acquire @lock, we set the 801 * Before testing whether we can acquire @lock, we set the
782 * RT_MUTEX_HAS_WAITERS bit in @lock->owner. This forces all 802 * 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,
902 struct rt_mutex *next_lock; 922 struct rt_mutex *next_lock;
903 int chain_walk = 0, res; 923 int chain_walk = 0, res;
904 924
925 lockdep_assert_held(&lock->wait_lock);
926
905 /* 927 /*
906 * Early deadlock detection. We really don't want the task to 928 * Early deadlock detection. We really don't want the task to
907 * enqueue on itself just to untangle the mess later. It's not 929 * 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,
919 waiter->task = task; 941 waiter->task = task;
920 waiter->lock = lock; 942 waiter->lock = lock;
921 waiter->prio = task->prio; 943 waiter->prio = task->prio;
944 waiter->deadline = task->dl.deadline;
922 945
923 /* Get the top priority waiter on the lock */ 946 /* Get the top priority waiter on the lock */
924 if (rt_mutex_has_waiters(lock)) 947 if (rt_mutex_has_waiters(lock))
@@ -1036,6 +1059,8 @@ static void remove_waiter(struct rt_mutex *lock,
1036 struct task_struct *owner = rt_mutex_owner(lock); 1059 struct task_struct *owner = rt_mutex_owner(lock);
1037 struct rt_mutex *next_lock; 1060 struct rt_mutex *next_lock;
1038 1061
1062 lockdep_assert_held(&lock->wait_lock);
1063
1039 raw_spin_lock(&current->pi_lock); 1064 raw_spin_lock(&current->pi_lock);
1040 rt_mutex_dequeue(lock, waiter); 1065 rt_mutex_dequeue(lock, waiter);
1041 current->pi_blocked_on = NULL; 1066 current->pi_blocked_on = NULL;