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 ad@.
This commit is contained in:
haad 2010-05-11 22:26:00 +00:00
parent 1616addc6a
commit 6af3749398
2 changed files with 57 additions and 8 deletions

View File

@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: kern_kthread.c,v 1.27 2009/10/21 21:12:06 rmind Exp
/*
* 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 @@ kthread_create(pri_t pri, int flag, struct cpu_info *ci,
{
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 @@ kthread_create(pri_t pri, int flag, struct cpu_info *ci,
} 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 @@ kthread_create(pri_t pri, int flag, struct cpu_info *ci,
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 @@ kthread_create(pri_t pri, int flag, struct cpu_info *ci,
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 @@ kthread_exit(int ecode)
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;
}

View File

@ -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 @@ int kthread_create(pri_t, int, struct cpu_info *,
__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_ */