git: 7951b4f4f99c - stable/13 - _utmx_op: don't recurse on chain busy

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Fri, 22 Nov 2024 04:53:56 UTC
The branch stable/13 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=7951b4f4f99cc6e2cbd51c516dc083e031c3babf

commit 7951b4f4f99cc6e2cbd51c516dc083e031c3babf
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2024-11-13 22:18:40 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2024-11-22 04:53:44 +0000

    _utmx_op: don't recurse on chain busy
    
    In handling a PP mutex, we'll busy it as soon as we enter the loop and
    unbusy it either prior to sleeping or at exit time.  In this particular
    case, if we fail to transition the mutex from OWNERDEAD -> owned because
    of casueword(9) failure and the suspend check fails, we'll start over
    and attempt to busy an already-busied chain and irrecoverably lock up
    both this thread and anything else that tries to busy the chain.
    
    Unbusy the chain prior to restarting because I couldn't decide if that
    was a better or worse idea than just keeping track of whether we dirtied
    it in do_lock_pp() and avoiding re-dirty.  This is marginally easier to
    reason about as it returns us to expected state on entry to the loop.
    
    While we're here, simplify the code a bit as `error` will be clobbered
    right after the branch anyways.
    
    Reviewed by:    kib, olce (both earlier version)
    
    (cherry picked from commit f660777865fcc28e147b51362412e0286e7df78e)
---
 sys/kern/kern_umtx.c | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 23087cf4269e..61b86d0b62b1 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -2605,11 +2605,9 @@ do_lock_pp(struct thread *td, struct umutex *m, uint32_t flags,
 			 */
 			if (error == 0) {
 				error = thread_check_susp(td, false);
-				if (error == 0) {
-					if (try != 0)
-						error = EBUSY;
-					else
-						continue;
+				if (error == 0 && try == 0) {
+					umtxq_unbusy_unlocked(&uq->uq_key);
+					continue;
 				}
 				error = 0;
 			}