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 | |
| 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>
| -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); |
