Module Name: src
Committed By: riastradh
Date: Mon Jul 17 10:55:27 UTC 2023
Modified Files:
src/sys/kern: kern_kthread.c
Log Message:
kthread(9): Fix nested kthread_join.
No reason for one kthread_join to interfere with another, or to cause
non-cyclic dependencies to get stuck.
Uses struct lwp::l_private for this purpose, which for user threads
stores the tls pointer. I don't think anything in kthread(9) uses
l_private -- generally kernel threads will use lwp specificdata. But
maybe this should use a new member instead, or a union member with an
existing pointer for the purpose.
To generate a diff of this commit:
cvs rdiff -u -r1.47 -r1.48 src/sys/kern/kern_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/kern/kern_kthread.c
diff -u src/sys/kern/kern_kthread.c:1.47 src/sys/kern/kern_kthread.c:1.48
--- src/sys/kern/kern_kthread.c:1.47 Tue Sep 13 09:37:49 2022
+++ src/sys/kern/kern_kthread.c Mon Jul 17 10:55:27 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_kthread.c,v 1.47 2022/09/13 09:37:49 riastradh Exp $ */
+/* $NetBSD: kern_kthread.c,v 1.48 2023/07/17 10:55:27 riastradh Exp $ */
/*-
* Copyright (c) 1998, 1999, 2007, 2009, 2019 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.47 2022/09/13 09:37:49 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.48 2023/07/17 10:55:27 riastradh Exp $");
#include <sys/param.h>
#include <sys/cpu.h>
@@ -45,7 +45,6 @@ __KERNEL_RCSID(0, "$NetBSD: kern_kthread
#include <uvm/uvm_extern.h>
-static lwp_t * kthread_jtarget;
static kmutex_t kthread_lock;
static kcondvar_t kthread_cv;
@@ -55,7 +54,6 @@ kthread_sysinit(void)
mutex_init(&kthread_lock, MUTEX_DEFAULT, IPL_NONE);
cv_init(&kthread_cv, "kthrwait");
- kthread_jtarget = NULL;
}
/*
@@ -172,11 +170,14 @@ kthread_exit(int ecode)
/* Barrier for joining. */
if (l->l_pflag & LP_MUSTJOIN) {
+ bool *exitedp;
+
mutex_enter(&kthread_lock);
- while (kthread_jtarget != l) {
+ while ((exitedp = l->l_private) == NULL) {
cv_wait(&kthread_cv, &kthread_lock);
}
- kthread_jtarget = NULL;
+ KASSERT(!*exitedp);
+ *exitedp = true;
cv_broadcast(&kthread_cv);
mutex_exit(&kthread_lock);
}
@@ -197,22 +198,21 @@ kthread_exit(int ecode)
int
kthread_join(lwp_t *l)
{
+ bool exited = false;
KASSERT((l->l_flag & LW_SYSTEM) != 0);
KASSERT((l->l_pflag & LP_MUSTJOIN) != 0);
/*
- * - Wait if some other thread has occupied the target.
- * - Specify our kthread as a target and notify it.
- * - Wait for the target kthread to notify us.
+ * - Ask the kthread to write to `exited'.
+ * - After this, touching l is forbidden -- it may be freed.
+ * - Wait until the kthread has written to `exited'.
*/
mutex_enter(&kthread_lock);
- while (kthread_jtarget) {
- cv_wait(&kthread_cv, &kthread_lock);
- }
- kthread_jtarget = l;
+ KASSERT(l->l_private == NULL);
+ l->l_private = &exited;
cv_broadcast(&kthread_cv);
- while (kthread_jtarget == l) {
+ while (!exited) {
cv_wait(&kthread_cv, &kthread_lock);
}
mutex_exit(&kthread_lock);