Fix compat10 semaphore interface race
Wrong has-waiters and missing unconditional _count==0 check may cause infinite waiting with already non-zero count. 1) properly clear _has_waiters flag when waiting failed to start 2) always check _count before start waiting PR: 265997 Reviewed by: kib MFC after: 1 week Differential revision: https://reviews.freebsd.org/D36272
This commit is contained in:
parent
a358db5603
commit
768f6373eb
@ -3547,24 +3547,28 @@ do_sem_wait(struct thread *td, struct _usem *sem, struct _umtx_time *timeout)
|
||||
umtxq_insert(uq);
|
||||
umtxq_unlock(&uq->uq_key);
|
||||
rv = casueword32(&sem->_has_waiters, 0, &count1, 1);
|
||||
if (rv == 0)
|
||||
if (rv != -1)
|
||||
rv1 = fueword32(&sem->_count, &count);
|
||||
if (rv == -1 || (rv == 0 && (rv1 == -1 || count != 0)) ||
|
||||
(rv == 1 && count1 == 0)) {
|
||||
if (rv == -1 || rv1 == -1 || count != 0 || (rv == 1 && count1 == 0)) {
|
||||
if (rv == 0)
|
||||
suword32(&sem->_has_waiters, 0);
|
||||
umtxq_lock(&uq->uq_key);
|
||||
umtxq_unbusy(&uq->uq_key);
|
||||
umtxq_remove(uq);
|
||||
umtxq_unlock(&uq->uq_key);
|
||||
if (rv == 1) {
|
||||
rv = thread_check_susp(td, true);
|
||||
if (rv == 0)
|
||||
goto again;
|
||||
error = rv;
|
||||
if (rv == -1 || rv1 == -1) {
|
||||
error = EFAULT;
|
||||
goto out;
|
||||
}
|
||||
if (count != 0) {
|
||||
error = 0;
|
||||
goto out;
|
||||
}
|
||||
MPASS(rv == 1 && count1 == 0);
|
||||
rv = thread_check_susp(td, true);
|
||||
if (rv == 0)
|
||||
rv = rv1;
|
||||
error = rv == -1 ? EFAULT : 0;
|
||||
goto again;
|
||||
error = rv;
|
||||
goto out;
|
||||
}
|
||||
umtxq_lock(&uq->uq_key);
|
||||
|
Loading…
Reference in New Issue
Block a user