umtx: Fix a bug in do_lock_pp()

If the lock is unowned (i.e., owner == UMUTEX_CONTESTED), we might get a
spurious failure, and in that case we need to retry the loop.
Otherwise, the calling thread can end up sleeping forever.

The same problem exists in do_set_ceiling(), which open-codes
do_lock_pp(), so fix it there too.

Reviewed by:	olce
Reported by:	Daniel King <dmking@adacore.com>
MFC after:	2 weeks
Sponsored by:	Innovate UK
Differential Revision:	https://reviews.freebsd.org/D49031

(cherry picked from commit 4b79443927)
This commit is contained in:
Mark Johnston 2025-02-22 01:23:31 +00:00
parent bec64e75a5
commit 0ce82e9346

View file

@ -2618,6 +2618,10 @@ do_lock_pp(struct thread *td, struct umutex *m, uint32_t flags,
}
} else if (owner == UMUTEX_RB_NOTRECOV) {
error = ENOTRECOVERABLE;
} else if (owner == UMUTEX_CONTESTED) {
/* Spurious failure, retry. */
umtxq_unbusy_unlocked(&uq->uq_key);
continue;
}
if (try != 0)
@ -2824,6 +2828,10 @@ do_set_ceiling(struct thread *td, struct umutex *m, uint32_t ceiling,
} else if (owner == UMUTEX_RB_NOTRECOV) {
error = ENOTRECOVERABLE;
break;
} else if (owner == UMUTEX_CONTESTED) {
/* Spurious failure, retry. */
umtxq_unbusy_unlocked(&uq->uq_key);
continue;
}
/*