* Unlock a PI mutex. */
| 1994 | * Unlock a PI mutex. |
| 1995 | */ |
| 1996 | static int |
| 1997 | do_unlock_pi(struct thread *td, struct umutex *m, uint32_t flags, bool rb) |
| 1998 | { |
| 1999 | struct umtx_key key; |
| 2000 | struct umtx_q *uq_first, *uq_first2, *uq_me; |
| 2001 | struct umtx_pi *pi, *pi2; |
| 2002 | uint32_t id, new_owner, old, owner; |
| 2003 | int count, error, pri; |
| 2004 | |
| 2005 | id = td->td_tid; |
| 2006 | |
| 2007 | usrloop: |
| 2008 | /* |
| 2009 | * Make sure we own this mtx. |
| 2010 | */ |
| 2011 | error = fueword32(&m->m_owner, &owner); |
| 2012 | if (error == -1) |
| 2013 | return (EFAULT); |
| 2014 | |
| 2015 | if ((owner & ~UMUTEX_CONTESTED) != id) |
| 2016 | return (EPERM); |
| 2017 | |
| 2018 | new_owner = umtx_unlock_val(flags, rb); |
| 2019 | |
| 2020 | /* This should be done in userland */ |
| 2021 | if ((owner & UMUTEX_CONTESTED) == 0) { |
| 2022 | error = casueword32(&m->m_owner, owner, &old, new_owner); |
| 2023 | if (error == -1) |
| 2024 | return (EFAULT); |
| 2025 | if (error == 1) { |
| 2026 | error = thread_check_susp(td, true); |
| 2027 | if (error != 0) |
| 2028 | return (error); |
| 2029 | goto usrloop; |
| 2030 | } |
| 2031 | if (old == owner) |
| 2032 | return (0); |
| 2033 | owner = old; |
| 2034 | } |
| 2035 | |
| 2036 | /* We should only ever be in here for contested locks */ |
| 2037 | if ((error = umtx_key_get(m, (flags & UMUTEX_ROBUST) != 0 ? |
| 2038 | TYPE_PI_ROBUST_UMUTEX : TYPE_PI_UMUTEX, GET_SHARE(flags), |
| 2039 | &key)) != 0) |
| 2040 | return (error); |
| 2041 | |
| 2042 | umtxq_lock(&key); |
| 2043 | umtxq_busy(&key); |
| 2044 | count = umtxq_count_pi(&key, &uq_first); |
| 2045 | if (uq_first != NULL) { |
| 2046 | mtx_lock(&umtx_lock); |
| 2047 | pi = uq_first->uq_pi_blocked; |
| 2048 | KASSERT(pi != NULL, ("pi == NULL?")); |
| 2049 | if (pi->pi_owner != td && !(rb && pi->pi_owner == NULL)) { |
| 2050 | mtx_unlock(&umtx_lock); |
| 2051 | umtxq_unbusy(&key); |
| 2052 | umtxq_unlock(&key); |
| 2053 | umtx_key_release(&key); |
no test coverage detected