Pull up following revision(s) (requested by riastradh in ticket #1696):
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
This commit is contained in:
parent
c6bf52d6ed
commit
af56efbd87
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: linux_ww_mutex.c,v 1.7.2.2 2023/08/01 17:16:26 martin Exp $ */
|
||||
/* $NetBSD: linux_ww_mutex.c,v 1.7.2.3 2023/08/01 17:26:28 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.7.2.2 2023/08/01 17:16:26 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: linux_ww_mutex.c,v 1.7.2.3 2023/08/01 17:26:28 martin Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/atomic.h>
|
||||
|
@ -271,8 +271,14 @@ ww_mutex_state_wait(struct ww_mutex *mutex, enum ww_mutex_state state)
|
|||
|
||||
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 *mutex, enum ww_mutex_state state)
|
|||
|
||||
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 *mutex, struct ww_acquire_ctx *ctx)
|
|||
"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 *mutex, struct ww_acquire_ctx *ctx)
|
|||
"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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue