| 2532 | } |
| 2533 | |
| 2534 | static int |
| 2535 | do_cv_wait(struct thread *td, struct ucond *cv, struct umutex *m, |
| 2536 | struct timespec *timeout, u_long wflags) |
| 2537 | { |
| 2538 | struct abs_timeout timo; |
| 2539 | struct umtx_q *uq; |
| 2540 | uint32_t flags, clockid, hasw; |
| 2541 | int error; |
| 2542 | |
| 2543 | uq = td->td_umtxq; |
| 2544 | error = fueword32(&cv->c_flags, &flags); |
| 2545 | if (error == -1) |
| 2546 | return (EFAULT); |
| 2547 | error = umtx_key_get(cv, TYPE_CV, GET_SHARE(flags), &uq->uq_key); |
| 2548 | if (error != 0) |
| 2549 | return (error); |
| 2550 | |
| 2551 | if ((wflags & CVWAIT_CLOCKID) != 0) { |
| 2552 | error = fueword32(&cv->c_clockid, &clockid); |
| 2553 | if (error == -1) { |
| 2554 | umtx_key_release(&uq->uq_key); |
| 2555 | return (EFAULT); |
| 2556 | } |
| 2557 | if (clockid < CLOCK_REALTIME || |
| 2558 | clockid >= CLOCK_THREAD_CPUTIME_ID) { |
| 2559 | /* hmm, only HW clock id will work. */ |
| 2560 | umtx_key_release(&uq->uq_key); |
| 2561 | return (EINVAL); |
| 2562 | } |
| 2563 | } else { |
| 2564 | clockid = CLOCK_REALTIME; |
| 2565 | } |
| 2566 | |
| 2567 | umtxq_lock(&uq->uq_key); |
| 2568 | umtxq_busy(&uq->uq_key); |
| 2569 | umtxq_insert(uq); |
| 2570 | umtxq_unlock(&uq->uq_key); |
| 2571 | |
| 2572 | /* |
| 2573 | * Set c_has_waiters to 1 before releasing user mutex, also |
| 2574 | * don't modify cache line when unnecessary. |
| 2575 | */ |
| 2576 | error = fueword32(&cv->c_has_waiters, &hasw); |
| 2577 | if (error == 0 && hasw == 0) |
| 2578 | suword32(&cv->c_has_waiters, 1); |
| 2579 | |
| 2580 | umtxq_unbusy_unlocked(&uq->uq_key); |
| 2581 | |
| 2582 | error = do_unlock_umutex(td, m, false); |
| 2583 | |
| 2584 | if (timeout != NULL) |
| 2585 | abs_timeout_init(&timo, clockid, (wflags & CVWAIT_ABSTIME) != 0, |
| 2586 | timeout); |
| 2587 | |
| 2588 | umtxq_lock(&uq->uq_key); |
| 2589 | if (error == 0) { |
| 2590 | error = umtxq_sleep(uq, "ucond", timeout == NULL ? |
| 2591 | NULL : &timo); |
no test coverage detected