| 3161 | |
| 3162 | #if defined(COMPAT_FREEBSD9) || defined(COMPAT_FREEBSD10) |
| 3163 | static int |
| 3164 | do_sem_wait(struct thread *td, struct _usem *sem, struct _umtx_time *timeout) |
| 3165 | { |
| 3166 | struct abs_timeout timo; |
| 3167 | struct umtx_q *uq; |
| 3168 | uint32_t flags, count, count1; |
| 3169 | int error, rv, rv1; |
| 3170 | |
| 3171 | uq = td->td_umtxq; |
| 3172 | error = fueword32(&sem->_flags, &flags); |
| 3173 | if (error == -1) |
| 3174 | return (EFAULT); |
| 3175 | error = umtx_key_get(sem, TYPE_SEM, GET_SHARE(flags), &uq->uq_key); |
| 3176 | if (error != 0) |
| 3177 | return (error); |
| 3178 | |
| 3179 | if (timeout != NULL) |
| 3180 | abs_timeout_init2(&timo, timeout); |
| 3181 | |
| 3182 | again: |
| 3183 | umtxq_lock(&uq->uq_key); |
| 3184 | umtxq_busy(&uq->uq_key); |
| 3185 | umtxq_insert(uq); |
| 3186 | umtxq_unlock(&uq->uq_key); |
| 3187 | rv = casueword32(&sem->_has_waiters, 0, &count1, 1); |
| 3188 | if (rv == 0) |
| 3189 | rv1 = fueword32(&sem->_count, &count); |
| 3190 | if (rv == -1 || (rv == 0 && (rv1 == -1 || count != 0)) || |
| 3191 | (rv == 1 && count1 == 0)) { |
| 3192 | umtxq_lock(&uq->uq_key); |
| 3193 | umtxq_unbusy(&uq->uq_key); |
| 3194 | umtxq_remove(uq); |
| 3195 | umtxq_unlock(&uq->uq_key); |
| 3196 | if (rv == 1) { |
| 3197 | rv = thread_check_susp(td, true); |
| 3198 | if (rv == 0) |
| 3199 | goto again; |
| 3200 | error = rv; |
| 3201 | goto out; |
| 3202 | } |
| 3203 | if (rv == 0) |
| 3204 | rv = rv1; |
| 3205 | error = rv == -1 ? EFAULT : 0; |
| 3206 | goto out; |
| 3207 | } |
| 3208 | umtxq_lock(&uq->uq_key); |
| 3209 | umtxq_unbusy(&uq->uq_key); |
| 3210 | |
| 3211 | error = umtxq_sleep(uq, "usem", timeout == NULL ? NULL : &timo); |
| 3212 | |
| 3213 | if ((uq->uq_flags & UQF_UMTXQ) == 0) |
| 3214 | error = 0; |
| 3215 | else { |
| 3216 | umtxq_remove(uq); |
| 3217 | /* A relative timeout cannot be restarted. */ |
| 3218 | if (error == ERESTART && timeout != NULL && |
| 3219 | (timeout->_flags & UMTX_ABSTIME) == 0) |
| 3220 | error = EINTR; |
no test coverage detected