summaryrefslogtreecommitdiffstats
path: root/include/linux/mutex.h
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2017-01-11 14:17:48 +0100
committerIngo Molnar <mingo@kernel.org>2017-01-14 11:14:38 +0100
commite274795ea7b7caa0fd74ef651594382a69e2a951 (patch)
tree345b942f86040c9361e1a2b0bc45f58f7b48bb19 /include/linux/mutex.h
parent52b94129f274937e4c25dd17b76697664a3c43c9 (diff)
downloadlinux-stable-e274795ea7b7caa0fd74ef651594382a69e2a951.tar.gz
linux-stable-e274795ea7b7caa0fd74ef651594382a69e2a951.tar.bz2
linux-stable-e274795ea7b7caa0fd74ef651594382a69e2a951.zip
locking/mutex: Fix mutex handoff
While reviewing the ww_mutex patches, I noticed that it was still possible to (incorrectly) succeed for (incorrect) code like: mutex_lock(&a); mutex_lock(&a); This was possible if the second mutex_lock() would block (as expected) but then receive a spurious wakeup. At that point it would find itself at the front of the queue, request a handoff and instantly claim ownership and continue, since owner would point to itself. Avoid this scenario and simplify the code by introducing a third low bit to signal handoff pickup. So once we request handoff, unlock clears the handoff bit and sets the pickup bit along with the new owner. This also removes the need for the .handoff argument to __mutex_trylock(), since that becomes superfluous with PICKUP. In order to guarantee enough low bits, ensure task_struct alignment is at least L1_CACHE_BYTES (which seems a good ideal regardless). Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Fixes: 9d659ae14b54 ("locking/mutex: Add lock handoff to avoid starvation") Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'include/linux/mutex.h')
-rw-r--r--include/linux/mutex.h2
1 files changed, 1 insertions, 1 deletions
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index b97870f2debd..3e1fccb47f11 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -65,7 +65,7 @@ struct mutex {
static inline struct task_struct *__mutex_owner(struct mutex *lock)
{
- return (struct task_struct *)(atomic_long_read(&lock->owner) & ~0x03);
+ return (struct task_struct *)(atomic_long_read(&lock->owner) & ~0x07);
}
/*