aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/locking
diff options
context:
space:
mode:
authorDavidlohr Bueso <dave@stgolabs.net>2015-05-19 13:24:55 -0400
committerThomas Gleixner <tglx@linutronix.de>2015-06-18 16:27:46 -0400
commit45ab4effc3bee6f8a5cb05652b7bb895ec5b6a7a (patch)
tree330e0f345b3f5e485e0e1ba6926c9d2dd3c5350e /kernel/locking
parent6f9aad0bc37286c0441b57f0ba8cffee50715426 (diff)
locking/rtmutex: Implement lockless top-waiter wakeup
Mark the task for later wakeup after the wait_lock has been released. This way, once the next task is awoken, it will have a better chance to of finding the wait_lock free when continuing executing in __rt_mutex_slowlock() when trying to acquire the rtmutex, calling try_to_take_rt_mutex(). Upon contended scenarios, other tasks attempting take the lock may acquire it first, right after the wait_lock is released, but (a) this can also occur with the current code, as it relies on the spinlock fairness, and (b) we are dealing with the top-waiter anyway, so it will always take the lock next. Signed-off-by: Davidlohr Bueso <dbueso@suse.de> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Mike Galbraith <umgwanakikbuti@gmail.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Cc: Davidlohr Bueso <dave@stgolabs.net> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1432056298-18738-2-git-send-email-dave@stgolabs.net Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/locking')
-rw-r--r--kernel/locking/rtmutex.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index b025295f4966..44ee8f85a78b 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -955,14 +955,13 @@ static int task_blocks_on_rt_mutex(struct rt_mutex *lock,
955} 955}
956 956
957/* 957/*
958 * Wake up the next waiter on the lock.
959 *
960 * Remove the top waiter from the current tasks pi waiter list and 958 * Remove the top waiter from the current tasks pi waiter list and
961 * wake it up. 959 * queue it up.
962 * 960 *
963 * Called with lock->wait_lock held. 961 * Called with lock->wait_lock held.
964 */ 962 */
965static void wakeup_next_waiter(struct rt_mutex *lock) 963static void mark_wakeup_next_waiter(struct wake_q_head *wake_q,
964 struct rt_mutex *lock)
966{ 965{
967 struct rt_mutex_waiter *waiter; 966 struct rt_mutex_waiter *waiter;
968 unsigned long flags; 967 unsigned long flags;
@@ -991,12 +990,7 @@ static void wakeup_next_waiter(struct rt_mutex *lock)
991 990
992 raw_spin_unlock_irqrestore(&current->pi_lock, flags); 991 raw_spin_unlock_irqrestore(&current->pi_lock, flags);
993 992
994 /* 993 wake_q_add(wake_q, waiter->task);
995 * It's safe to dereference waiter as it cannot go away as
996 * long as we hold lock->wait_lock. The waiter task needs to
997 * acquire it in order to dequeue the waiter.
998 */
999 wake_up_process(waiter->task);
1000} 994}
1001 995
1002/* 996/*
@@ -1258,6 +1252,8 @@ static inline int rt_mutex_slowtrylock(struct rt_mutex *lock)
1258static void __sched 1252static void __sched
1259rt_mutex_slowunlock(struct rt_mutex *lock) 1253rt_mutex_slowunlock(struct rt_mutex *lock)
1260{ 1254{
1255 WAKE_Q(wake_q);
1256
1261 raw_spin_lock(&lock->wait_lock); 1257 raw_spin_lock(&lock->wait_lock);
1262 1258
1263 debug_rt_mutex_unlock(lock); 1259 debug_rt_mutex_unlock(lock);
@@ -1306,10 +1302,13 @@ rt_mutex_slowunlock(struct rt_mutex *lock)
1306 /* 1302 /*
1307 * The wakeup next waiter path does not suffer from the above 1303 * The wakeup next waiter path does not suffer from the above
1308 * race. See the comments there. 1304 * race. See the comments there.
1305 *
1306 * Queue the next waiter for wakeup once we release the wait_lock.
1309 */ 1307 */
1310 wakeup_next_waiter(lock); 1308 mark_wakeup_next_waiter(&wake_q, lock);
1311 1309
1312 raw_spin_unlock(&lock->wait_lock); 1310 raw_spin_unlock(&lock->wait_lock);
1311 wake_up_q(&wake_q);
1313 1312
1314 /* Undo pi boosting if necessary: */ 1313 /* Undo pi boosting if necessary: */
1315 rt_mutex_adjust_prio(current); 1314 rt_mutex_adjust_prio(current);