* Unlock PTHREAD_PRIO_NONE protocol POSIX mutex. */
| 1160 | * Unlock PTHREAD_PRIO_NONE protocol POSIX mutex. |
| 1161 | */ |
| 1162 | static int |
| 1163 | do_unlock_normal(struct thread *td, struct umutex *m, uint32_t flags, bool rb) |
| 1164 | { |
| 1165 | struct umtx_key key; |
| 1166 | uint32_t owner, old, id, newlock; |
| 1167 | int error, count; |
| 1168 | |
| 1169 | id = td->td_tid; |
| 1170 | |
| 1171 | again: |
| 1172 | /* |
| 1173 | * Make sure we own this mtx. |
| 1174 | */ |
| 1175 | error = fueword32(&m->m_owner, &owner); |
| 1176 | if (error == -1) |
| 1177 | return (EFAULT); |
| 1178 | |
| 1179 | if ((owner & ~UMUTEX_CONTESTED) != id) |
| 1180 | return (EPERM); |
| 1181 | |
| 1182 | newlock = umtx_unlock_val(flags, rb); |
| 1183 | if ((owner & UMUTEX_CONTESTED) == 0) { |
| 1184 | error = casueword32(&m->m_owner, owner, &old, newlock); |
| 1185 | if (error == -1) |
| 1186 | return (EFAULT); |
| 1187 | if (error == 1) { |
| 1188 | error = thread_check_susp(td, false); |
| 1189 | if (error != 0) |
| 1190 | return (error); |
| 1191 | goto again; |
| 1192 | } |
| 1193 | MPASS(old == owner); |
| 1194 | return (0); |
| 1195 | } |
| 1196 | |
| 1197 | /* We should only ever be in here for contested locks */ |
| 1198 | if ((error = umtx_key_get(m, TYPE_NORMAL_UMUTEX, GET_SHARE(flags), |
| 1199 | &key)) != 0) |
| 1200 | return (error); |
| 1201 | |
| 1202 | umtxq_lock(&key); |
| 1203 | umtxq_busy(&key); |
| 1204 | count = umtxq_count(&key); |
| 1205 | umtxq_unlock(&key); |
| 1206 | |
| 1207 | /* |
| 1208 | * When unlocking the umtx, it must be marked as unowned if |
| 1209 | * there is zero or one thread only waiting for it. |
| 1210 | * Otherwise, it must be marked as contested. |
| 1211 | */ |
| 1212 | if (count > 1) |
| 1213 | newlock |= UMUTEX_CONTESTED; |
| 1214 | error = casueword32(&m->m_owner, owner, &old, newlock); |
| 1215 | umtxq_lock(&key); |
| 1216 | umtxq_signal(&key, 1); |
| 1217 | umtxq_unbusy(&key); |
| 1218 | umtxq_unlock(&key); |
| 1219 | umtx_key_release(&key); |
no test coverage detected