diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c --- a/sys/kern/kern_umtx.c +++ b/sys/kern/kern_umtx.c @@ -834,8 +834,17 @@ } error = msleep_sbt(uq, &uc->uc_lock, PCATCH | PDROP, wmesg, sbt, 0, flags); +retrylock: uc = umtxq_getchain(&uq->uq_key); mtx_lock(&uc->uc_lock); + if (__predict_false(uc != umtxq_getchain(&uq->uq_key))) { + /* + * Deal with race with umtxq_requeue(). It holds + * both the old lock and the new lock. + */ + mtx_unlock(&uc->uc_lock); + goto retrylock; + } if (error == EINTR || error == ERESTART) break; if (error == EWOULDBLOCK && (flags & C_ABSOLUTE) != 0) {