* Fetch and compare value, sleep on the address if value is not changed. */
| 912 | * Fetch and compare value, sleep on the address if value is not changed. |
| 913 | */ |
| 914 | static int |
| 915 | do_wait(struct thread *td, void *addr, u_long id, |
| 916 | struct _umtx_time *timeout, int compat32, int is_private) |
| 917 | { |
| 918 | struct abs_timeout timo; |
| 919 | struct umtx_q *uq; |
| 920 | u_long tmp; |
| 921 | uint32_t tmp32; |
| 922 | int error = 0; |
| 923 | |
| 924 | uq = td->td_umtxq; |
| 925 | if ((error = umtx_key_get(addr, TYPE_SIMPLE_WAIT, |
| 926 | is_private ? THREAD_SHARE : AUTO_SHARE, &uq->uq_key)) != 0) |
| 927 | return (error); |
| 928 | |
| 929 | if (timeout != NULL) |
| 930 | abs_timeout_init2(&timo, timeout); |
| 931 | |
| 932 | umtxq_lock(&uq->uq_key); |
| 933 | umtxq_insert(uq); |
| 934 | umtxq_unlock(&uq->uq_key); |
| 935 | if (compat32 == 0) { |
| 936 | error = fueword(addr, &tmp); |
| 937 | if (error != 0) |
| 938 | error = EFAULT; |
| 939 | } else { |
| 940 | error = fueword32(addr, &tmp32); |
| 941 | if (error == 0) |
| 942 | tmp = tmp32; |
| 943 | else |
| 944 | error = EFAULT; |
| 945 | } |
| 946 | umtxq_lock(&uq->uq_key); |
| 947 | if (error == 0) { |
| 948 | if (tmp == id) |
| 949 | error = umtxq_sleep(uq, "uwait", timeout == NULL ? |
| 950 | NULL : &timo); |
| 951 | if ((uq->uq_flags & UQF_UMTXQ) == 0) |
| 952 | error = 0; |
| 953 | else |
| 954 | umtxq_remove(uq); |
| 955 | } else if ((uq->uq_flags & UQF_UMTXQ) != 0) { |
| 956 | umtxq_remove(uq); |
| 957 | } |
| 958 | umtxq_unlock(&uq->uq_key); |
| 959 | umtx_key_release(&uq->uq_key); |
| 960 | if (error == ERESTART) |
| 961 | error = EINTR; |
| 962 | return (error); |
| 963 | } |
| 964 | |
| 965 | /* |
| 966 | * Wake up threads sleeping on the specified address. |
no test coverage detected