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

Reply via email to