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