* Signal a userland semaphore. */
| 3350 | * Signal a userland semaphore. |
| 3351 | */ |
| 3352 | static int |
| 3353 | do_sem2_wake(struct thread *td, struct _usem2 *sem) |
| 3354 | { |
| 3355 | struct umtx_key key; |
| 3356 | int error, cnt, rv; |
| 3357 | uint32_t count, flags; |
| 3358 | |
| 3359 | rv = fueword32(&sem->_flags, &flags); |
| 3360 | if (rv == -1) |
| 3361 | return (EFAULT); |
| 3362 | if ((error = umtx_key_get(sem, TYPE_SEM, GET_SHARE(flags), &key)) != 0) |
| 3363 | return (error); |
| 3364 | umtxq_lock(&key); |
| 3365 | umtxq_busy(&key); |
| 3366 | cnt = umtxq_count(&key); |
| 3367 | if (cnt > 0) { |
| 3368 | /* |
| 3369 | * If this was the last sleeping thread, clear the waiters |
| 3370 | * flag in _count. |
| 3371 | */ |
| 3372 | if (cnt == 1) { |
| 3373 | umtxq_unlock(&key); |
| 3374 | rv = fueword32(&sem->_count, &count); |
| 3375 | while (rv != -1 && count & USEM_HAS_WAITERS) { |
| 3376 | rv = casueword32(&sem->_count, count, &count, |
| 3377 | count & ~USEM_HAS_WAITERS); |
| 3378 | if (rv == 1) { |
| 3379 | rv = thread_check_susp(td, true); |
| 3380 | if (rv != 0) |
| 3381 | break; |
| 3382 | } |
| 3383 | } |
| 3384 | if (rv == -1) |
| 3385 | error = EFAULT; |
| 3386 | else if (rv > 0) { |
| 3387 | error = rv; |
| 3388 | } |
| 3389 | umtxq_lock(&key); |
| 3390 | } |
| 3391 | |
| 3392 | umtxq_signal(&key, 1); |
| 3393 | } |
| 3394 | umtxq_unbusy(&key); |
| 3395 | umtxq_unlock(&key); |
| 3396 | umtx_key_release(&key); |
| 3397 | return (error); |
| 3398 | } |
| 3399 | |
| 3400 | inline int |
| 3401 | umtx_copyin_timeout(const void *uaddr, struct timespec *tsp) |
no test coverage detected