diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2015-12-19 15:07:39 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2015-12-20 06:43:24 -0500 |
commit | ecb38b78f698a51988ec456751b20440e54702fb (patch) | |
tree | de40cc51d6670284bd60f5f77e13c85632d86a28 /kernel/futex.c | |
parent | 29e9ee5d48c35d6cf8afe09bdf03f77125c9ac11 (diff) |
futex: Document pi_state refcounting in requeue code
Documentation of the pi_state refcounting in the requeue code is non
existent. Add it.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Darren Hart <darren@dvhart.com>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Bhuvanesh_Surachari@mentor.com
Cc: Andy Lowe <Andy_Lowe@mentor.com>
Link: http://lkml.kernel.org/r/20151219200607.335938312@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/futex.c')
-rw-r--r-- | kernel/futex.c | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/kernel/futex.c b/kernel/futex.c index f1581ff47122..20c468356b90 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
@@ -1709,27 +1709,31 @@ retry_private: | |||
1709 | * exist yet, look it up one more time to ensure we have a | 1709 | * exist yet, look it up one more time to ensure we have a |
1710 | * reference to it. If the lock was taken, ret contains the | 1710 | * reference to it. If the lock was taken, ret contains the |
1711 | * vpid of the top waiter task. | 1711 | * vpid of the top waiter task. |
1712 | * If the lock was not taken, we have pi_state and an initial | ||
1713 | * refcount on it. In case of an error we have nothing. | ||
1712 | */ | 1714 | */ |
1713 | if (ret > 0) { | 1715 | if (ret > 0) { |
1714 | WARN_ON(pi_state); | 1716 | WARN_ON(pi_state); |
1715 | drop_count++; | 1717 | drop_count++; |
1716 | task_count++; | 1718 | task_count++; |
1717 | /* | 1719 | /* |
1718 | * If we acquired the lock, then the user | 1720 | * If we acquired the lock, then the user space value |
1719 | * space value of uaddr2 should be vpid. It | 1721 | * of uaddr2 should be vpid. It cannot be changed by |
1720 | * cannot be changed by the top waiter as it | 1722 | * the top waiter as it is blocked on hb2 lock if it |
1721 | * is blocked on hb2 lock if it tries to do | 1723 | * tries to do so. If something fiddled with it behind |
1722 | * so. If something fiddled with it behind our | 1724 | * our back the pi state lookup might unearth it. So |
1723 | * back the pi state lookup might unearth | 1725 | * we rather use the known value than rereading and |
1724 | * it. So we rather use the known value than | 1726 | * handing potential crap to lookup_pi_state. |
1725 | * rereading and handing potential crap to | 1727 | * |
1726 | * lookup_pi_state. | 1728 | * If that call succeeds then we have pi_state and an |
1729 | * initial refcount on it. | ||
1727 | */ | 1730 | */ |
1728 | ret = lookup_pi_state(ret, hb2, &key2, &pi_state); | 1731 | ret = lookup_pi_state(ret, hb2, &key2, &pi_state); |
1729 | } | 1732 | } |
1730 | 1733 | ||
1731 | switch (ret) { | 1734 | switch (ret) { |
1732 | case 0: | 1735 | case 0: |
1736 | /* We hold a reference on the pi state. */ | ||
1733 | break; | 1737 | break; |
1734 | case -EFAULT: | 1738 | case -EFAULT: |
1735 | put_pi_state(pi_state); | 1739 | put_pi_state(pi_state); |
@@ -1804,19 +1808,37 @@ retry_private: | |||
1804 | * of requeue_pi if we couldn't acquire the lock atomically. | 1808 | * of requeue_pi if we couldn't acquire the lock atomically. |
1805 | */ | 1809 | */ |
1806 | if (requeue_pi) { | 1810 | if (requeue_pi) { |
1807 | /* Prepare the waiter to take the rt_mutex. */ | 1811 | /* |
1812 | * Prepare the waiter to take the rt_mutex. Take a | ||
1813 | * refcount on the pi_state and store the pointer in | ||
1814 | * the futex_q object of the waiter. | ||
1815 | */ | ||
1808 | atomic_inc(&pi_state->refcount); | 1816 | atomic_inc(&pi_state->refcount); |
1809 | this->pi_state = pi_state; | 1817 | this->pi_state = pi_state; |
1810 | ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex, | 1818 | ret = rt_mutex_start_proxy_lock(&pi_state->pi_mutex, |
1811 | this->rt_waiter, | 1819 | this->rt_waiter, |
1812 | this->task); | 1820 | this->task); |
1813 | if (ret == 1) { | 1821 | if (ret == 1) { |
1814 | /* We got the lock. */ | 1822 | /* |
1823 | * We got the lock. We do neither drop the | ||
1824 | * refcount on pi_state nor clear | ||
1825 | * this->pi_state because the waiter needs the | ||
1826 | * pi_state for cleaning up the user space | ||
1827 | * value. It will drop the refcount after | ||
1828 | * doing so. | ||
1829 | */ | ||
1815 | requeue_pi_wake_futex(this, &key2, hb2); | 1830 | requeue_pi_wake_futex(this, &key2, hb2); |
1816 | drop_count++; | 1831 | drop_count++; |
1817 | continue; | 1832 | continue; |
1818 | } else if (ret) { | 1833 | } else if (ret) { |
1819 | /* -EDEADLK */ | 1834 | /* |
1835 | * rt_mutex_start_proxy_lock() detected a | ||
1836 | * potential deadlock when we tried to queue | ||
1837 | * that waiter. Drop the pi_state reference | ||
1838 | * which we took above and remove the pointer | ||
1839 | * to the state from the waiters futex_q | ||
1840 | * object. | ||
1841 | */ | ||
1820 | this->pi_state = NULL; | 1842 | this->pi_state = NULL; |
1821 | put_pi_state(pi_state); | 1843 | put_pi_state(pi_state); |
1822 | goto out_unlock; | 1844 | goto out_unlock; |
@@ -1827,6 +1849,11 @@ retry_private: | |||
1827 | } | 1849 | } |
1828 | 1850 | ||
1829 | out_unlock: | 1851 | out_unlock: |
1852 | /* | ||
1853 | * We took an extra initial reference to the pi_state either | ||
1854 | * in futex_proxy_trylock_atomic() or in lookup_pi_state(). We | ||
1855 | * need to drop it here again. | ||
1856 | */ | ||
1830 | put_pi_state(pi_state); | 1857 | put_pi_state(pi_state); |
1831 | double_unlock_hb(hb1, hb2); | 1858 | double_unlock_hb(hb1, hb2); |
1832 | wake_up_q(&wake_q); | 1859 | wake_up_q(&wake_q); |