| 2680 | } |
| 2681 | |
| 2682 | static int |
| 2683 | do_rw_rdlock(struct thread *td, struct urwlock *rwlock, long fflag, |
| 2684 | struct _umtx_time *timeout) |
| 2685 | { |
| 2686 | struct abs_timeout timo; |
| 2687 | struct umtx_q *uq; |
| 2688 | uint32_t flags, wrflags; |
| 2689 | int32_t state, oldstate; |
| 2690 | int32_t blocked_readers; |
| 2691 | int error, error1, rv; |
| 2692 | |
| 2693 | uq = td->td_umtxq; |
| 2694 | error = fueword32(&rwlock->rw_flags, &flags); |
| 2695 | if (error == -1) |
| 2696 | return (EFAULT); |
| 2697 | error = umtx_key_get(rwlock, TYPE_RWLOCK, GET_SHARE(flags), &uq->uq_key); |
| 2698 | if (error != 0) |
| 2699 | return (error); |
| 2700 | |
| 2701 | if (timeout != NULL) |
| 2702 | abs_timeout_init2(&timo, timeout); |
| 2703 | |
| 2704 | wrflags = URWLOCK_WRITE_OWNER; |
| 2705 | if (!(fflag & URWLOCK_PREFER_READER) && !(flags & URWLOCK_PREFER_READER)) |
| 2706 | wrflags |= URWLOCK_WRITE_WAITERS; |
| 2707 | |
| 2708 | for (;;) { |
| 2709 | rv = fueword32(&rwlock->rw_state, &state); |
| 2710 | if (rv == -1) { |
| 2711 | umtx_key_release(&uq->uq_key); |
| 2712 | return (EFAULT); |
| 2713 | } |
| 2714 | |
| 2715 | /* try to lock it */ |
| 2716 | while (!(state & wrflags)) { |
| 2717 | if (__predict_false(URWLOCK_READER_COUNT(state) == |
| 2718 | URWLOCK_MAX_READERS)) { |
| 2719 | umtx_key_release(&uq->uq_key); |
| 2720 | return (EAGAIN); |
| 2721 | } |
| 2722 | rv = casueword32(&rwlock->rw_state, state, |
| 2723 | &oldstate, state + 1); |
| 2724 | if (rv == -1) { |
| 2725 | umtx_key_release(&uq->uq_key); |
| 2726 | return (EFAULT); |
| 2727 | } |
| 2728 | if (rv == 0) { |
| 2729 | MPASS(oldstate == state); |
| 2730 | umtx_key_release(&uq->uq_key); |
| 2731 | return (0); |
| 2732 | } |
| 2733 | error = thread_check_susp(td, true); |
| 2734 | if (error != 0) |
| 2735 | break; |
| 2736 | state = oldstate; |
| 2737 | } |
| 2738 | |
| 2739 | if (error) |
no test coverage detected