Module Name:    src
Committed By:   martin
Date:           Tue Aug  1 17:29:15 UTC 2023

Modified Files:
        src/sys/external/bsd/drm2/linux [netbsd-8]: linux_ww_mutex.c

Log Message:
Pull up following revision(s) (requested by riastradh in ticket #1876):

        sys/external/bsd/drm2/linux/linux_ww_mutex.c: revision 1.15

drm/linux_ww_mutex: Fix wait loops.

If cv_wait_sig returns because a signal is delivered, we may
nonetheless have been granted the lock.  It is harmless for us to
ignore this fact in three of the four paths, but in
ww_mutex_state_wait_sig, we may now have ownership of the lock and
MUST NOT return failure because the caller MUST release the lock
before destroying the ww_acquire_ctx.

While here, restructure the other three loops for clarity, so they
match the structure of the fourth and so they have a little less
impenetrable negation.

PR kern/57537


To generate a diff of this commit:
cvs rdiff -u -r1.2.10.5 -r1.2.10.6 \
    src/sys/external/bsd/drm2/linux/linux_ww_mutex.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/external/bsd/drm2/linux/linux_ww_mutex.c
diff -u src/sys/external/bsd/drm2/linux/linux_ww_mutex.c:1.2.10.5 src/sys/external/bsd/drm2/linux/linux_ww_mutex.c:1.2.10.6
--- src/sys/external/bsd/drm2/linux/linux_ww_mutex.c:1.2.10.5	Tue Aug  1 17:19:57 2023
+++ src/sys/external/bsd/drm2/linux/linux_ww_mutex.c	Tue Aug  1 17:29:15 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_ww_mutex.c,v 1.2.10.5 2023/08/01 17:19:57 martin Exp $	*/
+/*	$NetBSD: linux_ww_mutex.c,v 1.2.10.6 2023/08/01 17:29:15 martin Exp $	*/
 
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_ww_mutex.c,v 1.2.10.5 2023/08/01 17:19:57 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_ww_mutex.c,v 1.2.10.6 2023/08/01 17:29:15 martin Exp $");
 
 #include <sys/types.h>
 #include <sys/atomic.h>
@@ -271,8 +271,14 @@ ww_mutex_state_wait(struct ww_mutex *mut
 
 	KASSERT(mutex_owned(&mutex->wwm_lock));
 	KASSERT(mutex->wwm_state == state);
-	do cv_wait(&mutex->wwm_cv, &mutex->wwm_lock);
-	while (mutex->wwm_state == state);
+
+	for (;;) {
+		cv_wait(&mutex->wwm_cv, &mutex->wwm_lock);
+		if (mutex->wwm_state != state)
+			break;
+	}
+
+	KASSERT(mutex->wwm_state != state);
 }
 
 /*
@@ -295,18 +301,26 @@ ww_mutex_state_wait_sig(struct ww_mutex 
 
 	KASSERT(mutex_owned(&mutex->wwm_lock));
 	KASSERT(mutex->wwm_state == state);
-	do {
+
+	for (;;) {
 		/* XXX errno NetBSD->Linux */
 		ret = -cv_wait_sig(&mutex->wwm_cv, &mutex->wwm_lock);
+		if (mutex->wwm_state != state) {
+			ret = 0;
+			break;
+		}
 		if (ret) {
 			KASSERTMSG((ret == -EINTR || ret == -ERESTART),
 			    "ret=%d", ret);
 			ret = -EINTR;
 			break;
 		}
-	} while (mutex->wwm_state == state);
+	}
 
 	KASSERTMSG((ret == 0 || ret == -EINTR), "ret=%d", ret);
+	KASSERTMSG(ret != 0 || mutex->wwm_state != state,
+	    "ret=%d mutex=%p mutex->wwm_state=%d state=%d",
+	    ret, mutex, mutex->wwm_state, state);
 	return ret;
 }
 
@@ -348,12 +362,18 @@ ww_mutex_lock_wait(struct ww_mutex *mute
 	    "ticket number reused: %"PRId64" (%p) %"PRId64" (%p)",
 	    ctx->wwx_ticket, ctx, collision->wwx_ticket, collision);
 
-	do cv_wait(&mutex->wwm_cv, &mutex->wwm_lock);
-	while (!(((mutex->wwm_state == WW_CTX) ||
-		    (mutex->wwm_state == WW_WANTOWN)) &&
-		 (mutex->wwm_u.ctx == ctx)));
+	for (;;) {
+		cv_wait(&mutex->wwm_cv, &mutex->wwm_lock);
+		if ((mutex->wwm_state == WW_CTX ||
+			mutex->wwm_state == WW_WANTOWN) &&
+		    mutex->wwm_u.ctx == ctx)
+			break;
+	}
 
 	rb_tree_remove_node(&mutex->wwm_waiters, ctx);
+
+	KASSERT(mutex->wwm_state == WW_CTX || mutex->wwm_state == WW_WANTOWN);
+	KASSERT(mutex->wwm_u.ctx == ctx);
 }
 
 /*
@@ -396,21 +416,29 @@ ww_mutex_lock_wait_sig(struct ww_mutex *
 	    "ticket number reused: %"PRId64" (%p) %"PRId64" (%p)",
 	    ctx->wwx_ticket, ctx, collision->wwx_ticket, collision);
 
-	do {
+	for (;;) {
 		/* XXX errno NetBSD->Linux */
 		ret = -cv_wait_sig(&mutex->wwm_cv, &mutex->wwm_lock);
+		if ((mutex->wwm_state == WW_CTX ||
+			mutex->wwm_state == WW_WANTOWN) &&
+		    mutex->wwm_u.ctx == ctx) {
+			ret = 0;
+			break;
+		}
 		if (ret) {
 			KASSERTMSG((ret == -EINTR || ret == -ERESTART),
 			    "ret=%d", ret);
 			ret = -EINTR;
-			goto out;
+			break;
 		}
-	} while (!(((mutex->wwm_state == WW_CTX) ||
-		    (mutex->wwm_state == WW_WANTOWN)) &&
-		(mutex->wwm_u.ctx == ctx)));
+	}
+
+	rb_tree_remove_node(&mutex->wwm_waiters, ctx);
 
-out:	rb_tree_remove_node(&mutex->wwm_waiters, ctx);
 	KASSERTMSG((ret == 0 || ret == -EINTR), "ret=%d", ret);
+	KASSERT(ret != 0 ||
+	    mutex->wwm_state == WW_CTX || mutex->wwm_state == WW_WANTOWN);
+	KASSERT(ret != 0 || mutex->wwm_u.ctx == ctx);
 	return ret;
 }
 

Reply via email to