summaryrefslogtreecommitdiff
path: root/kernel/locking/mutex.c
diff options
context:
space:
mode:
authorRiley Andrews <riandrews@google.com>2015-08-10 14:02:29 -0700
committerTrilok Soni <tsoni@codeaurora.org>2016-08-25 23:54:08 -0700
commitdbc6f463a6fa80326c7f508245eb8ddae499d656 (patch)
tree7c0832e1a7c6aa1453016d73e172cbbda9038a2d /kernel/locking/mutex.c
parente97b6a0e0217f7c072fdad6c50673cd7a64348e1 (diff)
mutex: Add a delay into the SPIN_ON_OWNER wait loop.
On arm systems the spin on owner optimization can intermittently cause a lockup that's usually as long as the waiting thread's cpu timeslice. The repeated mutex aquisitions + atomics in a single spinning thread can completely lock out the owner from releasing the kernel mutex. The owner needs to acquire a spinlock on the relase path and this spinlock can share a monitor with the other locks and atomics on the waiter path. Rate limit the waiter so that the thread releasing the mutex never is starved. Bug 23036902 Change-Id: Ie1b64275a0c6141f94faaf3e63fcbf9b5438140c Signed-off-by: Riley Andrews <riandrews@google.com> Git-commit: 84d8ce7e0025cac60a8a379a7ee3e59d640fbc03 Git-repo: https://android.googlesource.com/kernel/msm.git Signed-off-by: Trilok Soni <tsoni@codeaurora.org>
Diffstat (limited to 'kernel/locking/mutex.c')
-rw-r--r--kernel/locking/mutex.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index 0551c219c40e..fb42418507ae 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/debug_locks.h>
#include <linux/osq_lock.h>
+#include <linux/delay.h>
/*
* In the DEBUG case we are using the "NULL fastpath" for mutexes,
@@ -378,6 +379,17 @@ static bool mutex_optimistic_spin(struct mutex *lock,
* values at the cost of a few extra spins.
*/
cpu_relax_lowlatency();
+
+ /*
+ * On arm systems, we must slow down the waiter's repeated
+ * aquisition of spin_mlock and atomics on the lock count, or
+ * we risk starving out a thread attempting to release the
+ * mutex. The mutex slowpath release must take spin lock
+ * wait_lock. This spin lock can share a monitor with the
+ * other waiter atomics in the mutex data structure, so must
+ * take care to rate limit the waiters.
+ */
+ udelay(1);
}
osq_unlock(&lock->osq);