Module Name: src
Committed By: riastradh
Date: Sun Dec 19 12:43:06 UTC 2021
Modified Files:
src/sys/external/bsd/drm2/linux: linux_kthread.c
Log Message:
drm: Work around busted kthread_join.
To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/sys/external/bsd/drm2/linux/linux_kthread.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_kthread.c
diff -u src/sys/external/bsd/drm2/linux/linux_kthread.c:1.8 src/sys/external/bsd/drm2/linux/linux_kthread.c:1.9
--- src/sys/external/bsd/drm2/linux/linux_kthread.c:1.8 Sun Dec 19 12:42:48 2021
+++ src/sys/external/bsd/drm2/linux/linux_kthread.c Sun Dec 19 12:43:05 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_kthread.c,v 1.8 2021/12/19 12:42:48 riastradh Exp $ */
+/* $NetBSD: linux_kthread.c,v 1.9 2021/12/19 12:43:05 riastradh Exp $ */
/*-
* Copyright (c) 2021 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_kthread.c,v 1.8 2021/12/19 12:42:48 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_kthread.c,v 1.9 2021/12/19 12:43:05 riastradh Exp $");
#include <sys/types.h>
@@ -53,6 +53,8 @@ struct task_struct {
bool kt_shouldstop:1;
bool kt_shouldpark:1;
bool kt_parked:1;
+ bool kt_exited:1;
+ int kt_ret;
int (*kt_func)(void *);
void *kt_cookie;
@@ -111,7 +113,19 @@ linux_kthread_start(void *cookie)
lwp_setspecific(linux_kthread_key, T);
ret = (*T->kt_func)(T->kt_cookie);
- kthread_exit(ret);
+
+ /*
+ * Mark the thread exited, set the return value, and wake any
+ * waiting kthread_stop.
+ */
+ mutex_enter(&T->kt_lock);
+ T->kt_exited = true;
+ T->kt_ret = ret;
+ cv_broadcast(&T->kt_cv);
+ mutex_exit(&T->kt_lock);
+
+ /* Exit the (NetBSD) kthread. */
+ kthread_exit(0);
}
static struct task_struct *
@@ -125,6 +139,12 @@ kthread_alloc(int (*func)(void *), void
mutex_init(&T->kt_lock, MUTEX_DEFAULT, IPL_VM);
cv_init(&T->kt_cv, "lnxkthrd");
+ T->kt_shouldstop = false;
+ T->kt_shouldpark = false;
+ T->kt_parked = false;
+ T->kt_exited = false;
+ T->kt_ret = 0;
+
T->kt_func = func;
T->kt_cookie = cookie;
T->kt_interlock = interlock;
@@ -137,6 +157,8 @@ static void
kthread_free(struct task_struct *T)
{
+ KASSERT(T->kt_exited);
+
cv_destroy(&T->kt_cv);
mutex_destroy(&T->kt_lock);
kmem_free(T, sizeof(*T));
@@ -150,7 +172,7 @@ kthread_run(int (*func)(void *), void *c
int error;
T = kthread_alloc(func, cookie, interlock, wq);
- error = kthread_create(PRI_NONE, KTHREAD_MPSAFE|KTHREAD_MUSTJOIN, NULL,
+ error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL,
linux_kthread_start, T, &T->kt_lwp, "%s", name);
if (error) {
kthread_free(T);
@@ -178,12 +200,16 @@ kthread_stop(struct task_struct *T)
cv_broadcast(&T->kt_cv);
DRM_SPIN_WAKEUP_ALL(T->kt_wq, T->kt_interlock);
- /* Release the locks. */
- mutex_exit(&T->kt_lock);
+ /* Release the interlock while we wait for thread to finish. */
spin_unlock(T->kt_interlock);
- /* Wait for the (NetBSD) kthread to exit. */
- ret = kthread_join(T->kt_lwp);
+ /* Wait for the thread to finish. */
+ while (!T->kt_exited)
+ cv_wait(&T->kt_cv, &T->kt_lock);
+
+ /* Grab the return code and release the lock -- we're done. */
+ ret = T->kt_ret;
+ mutex_exit(&T->kt_lock);
/* Free the (Linux) kthread. */
kthread_free(T);