Module Name: src Committed By: haad Date: Tue May 11 22:26:00 UTC 2010
Modified Files: src/sys/kern: kern_kthread.c src/sys/sys: kthread.h Log Message: Add support for kthread_join in our kernel thread implementation. This is used by zfs but I think that it can be generaly usefull. Thread need to be created with KTHREAD_JOINABLE flag and can be joined only once. When joinable thread was created it will not e automatically reaped from system and kthread_join must be called on it to reap it. Ok by a...@. To generate a diff of this commit: cvs rdiff -u -r1.27 -r1.28 src/sys/kern/kern_kthread.c cvs rdiff -u -r1.8 -r1.9 src/sys/sys/kthread.h 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.27 src/sys/kern/kern_kthread.c:1.28 --- src/sys/kern/kern_kthread.c:1.27 Wed Oct 21 21:12:06 2009 +++ src/sys/kern/kern_kthread.c Tue May 11 22:26:00 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_kthread.c,v 1.27 2009/10/21 21:12:06 rmind Exp $ */ +/* $NetBSD: kern_kthread.c,v 1.28 2010/05/11 22:26:00 haad Exp $ */ /*- * Copyright (c) 1998, 1999, 2007, 2009 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.27 2009/10/21 21:12:06 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.28 2010/05/11 22:26:00 haad Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -52,6 +52,12 @@ /* * Fork a kernel thread. Any process can request this to be done. + * + * With joinable kthreads KTHREAD_JOINABLE flag this should be known. + * 1. If you specify KTHREAD_JOINABLE, you must call kthread_join() to reap the thread. + * It will not be automatically reaped by the system. + * 2. For any given call to kthread_create(KTHREAD_JOINABLE), you may call kthread_join() + * only once on the returned lwp_t *. */ int kthread_create(pri_t pri, int flag, struct cpu_info *ci, @@ -60,10 +66,11 @@ { lwp_t *l; vaddr_t uaddr; - int error; + int error, lc, lwp_flags; va_list ap; - int lc; + lwp_flags = LWP_DETACHED; + uaddr = uvm_uarea_alloc(); if (uaddr == 0) { return ENOMEM; @@ -73,7 +80,12 @@ } else { lc = SCHED_RR; } - error = lwp_create(&lwp0, &proc0, uaddr, LWP_DETACHED, NULL, + + if ((flag & KTHREAD_JOINABLE) != 0) { + lwp_flags &= ~LWP_DETACHED; + } + + error = lwp_create(&lwp0, &proc0, uaddr, lwp_flags, NULL, 0, func, arg, &l, lc); if (error) { uvm_uarea_free(uaddr); @@ -82,7 +94,7 @@ if (fmt != NULL) { l->l_name = kmem_alloc(MAXCOMLEN, KM_SLEEP); if (l->l_name == NULL) { - lwp_exit(l); + kthread_destroy(l); return ENOMEM; } va_start(ap, fmt); @@ -97,6 +109,11 @@ KASSERT((flag & KTHREAD_MPSAFE) != 0); } + /* Joinable kthread can't be NULL. */ + if ((flag & KTHREAD_JOINABLE) != 0) { + KASSERT(l != NULL); + } + if (pri == PRI_NONE) { if ((flag & KTHREAD_TS) != 0) { /* Maximum user priority level. */ @@ -182,9 +199,39 @@ void kthread_destroy(lwp_t *l) { - + proc_t *p; + KASSERT((l->l_flag & LW_SYSTEM) != 0); KASSERT(l->l_stat == LSIDL); + p = l->l_proc; + + /* Add LRP_DETACHED flag because we can have joinable kthread now. */ + mutex_enter(p->p_lock); + l->l_prflag |= LPR_DETACHED; + mutex_exit(p->p_lock); + lwp_exit(l); } + +/* + * Wait for a kthread to exit, as pthread_join(). + */ +int +kthread_join(lwp_t *l) +{ + lwpid_t departed; + proc_t *p; + int error; + + KASSERT((l->l_flag & LW_SYSTEM) != 0); + KASSERT((l->l_prflag & LPR_DETACHED) == 0); + + p = l->l_proc; + + mutex_enter(p->p_lock); + error = lwp_wait1(curlwp, l->l_lid, &departed, LWPWAIT_EXITCONTROL); + mutex_exit(p->p_lock); + + return error; +} Index: src/sys/sys/kthread.h diff -u src/sys/sys/kthread.h:1.8 src/sys/sys/kthread.h:1.9 --- src/sys/sys/kthread.h:1.8 Thu Jan 29 22:00:26 2009 +++ src/sys/sys/kthread.h Tue May 11 22:26:00 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: kthread.h,v 1.8 2009/01/29 22:00:26 ad Exp $ */ +/* $NetBSD: kthread.h,v 1.9 2010/05/11 22:26:00 haad Exp $ */ /*- * Copyright (c) 1998, 2007, 2009 The NetBSD Foundation, Inc. @@ -44,6 +44,7 @@ #define KTHREAD_MPSAFE 0x02 /* does not need kernel_lock */ #define KTHREAD_INTR 0x04 /* interrupt handler */ #define KTHREAD_TS 0x08 /* timeshared */ +#define KTHREAD_JOINABLE 0x10 /* joinable thread */ int kthread_create(pri_t, int, struct cpu_info *, void (*)(void *), void *, @@ -51,6 +52,7 @@ __attribute__((__format__(__printf__,7,8))); void kthread_exit(int) __dead; void kthread_destroy(lwp_t *); +int kthread_join(lwp_t *); #endif /* _KERNEL */ #endif /* _SYS_KTHREAD_H_ */