]> git.baikalelectronics.ru Git - kernel.git/commit
futex: Drop hb->lock before enqueueing on the rtmutex
authorPeter Zijlstra <peterz@infradead.org>
Wed, 22 Mar 2017 10:36:00 +0000 (11:36 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 23 Mar 2017 18:14:59 +0000 (19:14 +0100)
commit5e77a7a1c5d513f53b27ebe23ba2de99f02cae83
tree162dda41c7fd9129019c28e86b873c42925acb17
parentb590dc6850c4e9d0247577cb9cad85748922a963
futex: Drop hb->lock before enqueueing on the rtmutex

When PREEMPT_RT_FULL does the spinlock -> rt_mutex substitution the PI
chain code will (falsely) report a deadlock and BUG.

The problem is that it hold hb->lock (now an rt_mutex) while doing
task_blocks_on_rt_mutex on the futex's pi_state::rtmutex. This, when
interleaved just right with futex_unlock_pi() leads it to believe to see an
AB-BA deadlock.

  Task1 (holds rt_mutex, Task2 (does FUTEX_LOCK_PI)
         does FUTEX_UNLOCK_PI)

lock hb->lock
lock rt_mutex (as per start_proxy)
  lock hb->lock

Which is a trivial AB-BA.

It is not an actual deadlock, because it won't be holding hb->lock by the
time it actually blocks on the rt_mutex, but the chainwalk code doesn't
know that and it would be a nightmare to handle this gracefully.

To avoid this problem, do the same as in futex_unlock_pi() and drop
hb->lock after acquiring wait_lock. This still fully serializes against
futex_unlock_pi(), since adding to the wait_list does the very same lock
dance, and removing it holds both locks.

Aside of solving the RT problem this makes the lock and unlock mechanism
symetric and reduces the hb->lock held time.

Reported-and-tested-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: juri.lelli@arm.com
Cc: xlpang@redhat.com
Cc: rostedt@goodmis.org
Cc: mathieu.desnoyers@efficios.com
Cc: jdesfossez@efficios.com
Cc: dvhart@infradead.org
Cc: bristot@redhat.com
Link: http://lkml.kernel.org/r/20170322104152.161341537@infradead.org
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
kernel/futex.c
kernel/locking/rtmutex.c
kernel/locking/rtmutex_common.h