Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/kern kthread(9): Fix nested kthread_join.



details:   https://anonhg.NetBSD.org/src/rev/cb2de9b218f8
branches:  trunk
changeset: 377553:cb2de9b218f8
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Mon Jul 17 10:55:27 2023 +0000

description:
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.

diffstat:

 sys/kern/kern_kthread.c |  28 ++++++++++++++--------------
 1 files changed, 14 insertions(+), 14 deletions(-)

diffs (81 lines):

diff -r a875c7fd4139 -r cb2de9b218f8 sys/kern/kern_kthread.c
--- a/sys/kern/kern_kthread.c   Mon Jul 17 10:12:54 2023 +0000
+++ b/sys/kern/kern_kthread.c   Mon Jul 17 10:55:27 2023 +0000
@@ -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 @@
 
 #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);



Home | Main Index | Thread Index | Old Index