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;
}