* Lock a PI mutex. */
| 1791 | * Lock a PI mutex. |
| 1792 | */ |
| 1793 | static int |
| 1794 | do_lock_pi(struct thread *td, struct umutex *m, uint32_t flags, |
| 1795 | struct _umtx_time *timeout, int try) |
| 1796 | { |
| 1797 | struct abs_timeout timo; |
| 1798 | struct umtx_q *uq; |
| 1799 | struct umtx_pi *pi, *new_pi; |
| 1800 | uint32_t id, old_owner, owner, old; |
| 1801 | int error, rv; |
| 1802 | |
| 1803 | id = td->td_tid; |
| 1804 | uq = td->td_umtxq; |
| 1805 | |
| 1806 | if ((error = umtx_key_get(m, (flags & UMUTEX_ROBUST) != 0 ? |
| 1807 | TYPE_PI_ROBUST_UMUTEX : TYPE_PI_UMUTEX, GET_SHARE(flags), |
| 1808 | &uq->uq_key)) != 0) |
| 1809 | return (error); |
| 1810 | |
| 1811 | if (timeout != NULL) |
| 1812 | abs_timeout_init2(&timo, timeout); |
| 1813 | |
| 1814 | umtxq_lock(&uq->uq_key); |
| 1815 | pi = umtx_pi_lookup(&uq->uq_key); |
| 1816 | if (pi == NULL) { |
| 1817 | new_pi = umtx_pi_alloc(M_NOWAIT); |
| 1818 | if (new_pi == NULL) { |
| 1819 | umtxq_unlock(&uq->uq_key); |
| 1820 | new_pi = umtx_pi_alloc(M_WAITOK); |
| 1821 | umtxq_lock(&uq->uq_key); |
| 1822 | pi = umtx_pi_lookup(&uq->uq_key); |
| 1823 | if (pi != NULL) { |
| 1824 | umtx_pi_free(new_pi); |
| 1825 | new_pi = NULL; |
| 1826 | } |
| 1827 | } |
| 1828 | if (new_pi != NULL) { |
| 1829 | new_pi->pi_key = uq->uq_key; |
| 1830 | umtx_pi_insert(new_pi); |
| 1831 | pi = new_pi; |
| 1832 | } |
| 1833 | } |
| 1834 | umtx_pi_ref(pi); |
| 1835 | umtxq_unlock(&uq->uq_key); |
| 1836 | |
| 1837 | /* |
| 1838 | * Care must be exercised when dealing with umtx structure. It |
| 1839 | * can fault on any access. |
| 1840 | */ |
| 1841 | for (;;) { |
| 1842 | /* |
| 1843 | * Try the uncontested case. This should be done in userland. |
| 1844 | */ |
| 1845 | rv = casueword32(&m->m_owner, UMUTEX_UNOWNED, &owner, id); |
| 1846 | /* The address was invalid. */ |
| 1847 | if (rv == -1) { |
| 1848 | error = EFAULT; |
| 1849 | break; |
| 1850 | } |
no test coverage detected