diff options
| author | thorpej <thorpej@NetBSD.org> | 2006-10-11 04:51:06 +0000 |
|---|---|---|
| committer | thorpej <thorpej@NetBSD.org> | 2006-10-11 04:51:06 +0000 |
| commit | 12e8bb915ecdcc0ea1abd49a1f6ccb4fcc0bcb20 (patch) | |
| tree | db1d91fc5bb489cf70061e3afd330a35f824fd93 | |
| parent | 42951eac0155e016655ae4978f5eb4bb9d2e5379 (diff) | |
Don't free specificdata in lwp_exit2(); it's not safe to block there.
Instead, free an LWP's specificdata from lwp_exit() (if it is not the
last LWP) or exit1() (if it is the last LWP). For consistency, free the
proc's specificdata from exit1() as well. Add lwp_finispecific() and
proc_finispecific() functions to make this more convenient.
| -rw-r--r-- | sys/kern/kern_exit.c | 11 | ||||
| -rw-r--r-- | sys/kern/kern_lwp.c | 33 | ||||
| -rw-r--r-- | sys/kern/kern_proc.c | 25 | ||||
| -rw-r--r-- | sys/sys/lwp.h | 3 | ||||
| -rw-r--r-- | sys/sys/proc.h | 3 |
5 files changed, 57 insertions, 18 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 9d336cae44f..bf0282772c9 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exit.c,v 1.159 2006/09/23 15:36:12 xtraeme Exp $ */ +/* $NetBSD: kern_exit.c,v 1.160 2006/10/11 04:51:06 thorpej Exp $ */ /*- * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc. @@ -74,7 +74,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.159 2006/09/23 15:36:12 xtraeme Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.160 2006/10/11 04:51:06 thorpej Exp $"); #include "opt_ktrace.h" #include "opt_perfctrs.h" @@ -343,6 +343,13 @@ exit1(struct lwp *l, int rv) (*p->p_emul->e_proc_exit)(p); /* + * Finalize the last LWP's specificdata, as well as the + * specificdata for the proc itself. + */ + lwp_finispecific(l); + proc_finispecific(p); + + /* * Free the VM resources we're still holding on to. * We must do this from a valid thread because doing * so may block. This frees vmspace, which we don't diff --git a/sys/kern/kern_lwp.c b/sys/kern/kern_lwp.c index 1495268d34e..a685976018b 100644 --- a/sys/kern/kern_lwp.c +++ b/sys/kern/kern_lwp.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_lwp.c,v 1.44 2006/10/11 03:46:42 thorpej Exp $ */ +/* $NetBSD: kern_lwp.c,v 1.45 2006/10/11 04:51:06 thorpej Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.44 2006/10/11 03:46:42 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.45 2006/10/11 04:51:06 thorpej Exp $"); #include "opt_multiprocessor.h" @@ -435,8 +435,6 @@ lwp_wait1(struct lwp *l, lwpid_t lid, lwpid_t *departed, int flags) simple_unlock(&p->p_lock); /* XXX decrement limits */ - specificdata_fini(lwp_specificdata_domain, - &l->l_specdataref); pool_put(&lwp_pool, l2); return (0); @@ -579,6 +577,8 @@ lwp_exit(struct lwp *l) * the entire process (if that's not already going on). We do * so with an exit status of zero, because it's a "controlled" * exit, and because that's what Solaris does. + * + * Note: the last LWP's specificdata will be deleted here. */ if (((p->p_nlwps - p->p_nzlwps) == 1) && ((p->p_flag & P_WEXIT) == 0)) { DPRINTF(("lwp_exit: %d.%d calling exit1()\n", @@ -587,6 +587,9 @@ lwp_exit(struct lwp *l) /* NOTREACHED */ } + /* Delete the specificdata while it's still safe to sleep. */ + specificdata_fini(lwp_specificdata_domain, &l->l_specdataref); + s = proclist_lock_write(); LIST_REMOVE(l, l_list); proclist_unlock_write(s); @@ -650,7 +653,6 @@ lwp_exit2(struct lwp *l) if (l->l_flag & L_DETACHED) { /* Nobody waits for detached LWPs. */ - specificdata_fini(lwp_specificdata_domain, &l->l_specdataref); pool_put(&lwp_pool, l); KERNEL_UNLOCK(); } else { @@ -772,8 +774,7 @@ int lwp_specific_key_create(specificdata_key_t *keyp, specificdata_dtor_t dtor) { - return (specificdata_key_create(lwp_specificdata_domain, - keyp, dtor)); + return (specificdata_key_create(lwp_specificdata_domain, keyp, dtor)); } /* @@ -787,15 +788,31 @@ lwp_specific_key_delete(specificdata_key_t key) specificdata_key_delete(lwp_specificdata_domain, key); } +/* + * lwp_initspecific -- + * Initialize an LWP's specificdata container. + */ void lwp_initspecific(struct lwp *l) { int error; + error = specificdata_init(lwp_specificdata_domain, &l->l_specdataref); KASSERT(error == 0); } /* + * lwp_finispecific -- + * Finalize an LWP's specificdata container. + */ +void +lwp_finispecific(struct lwp *l) +{ + + specificdata_fini(lwp_specificdata_domain, &l->l_specdataref); +} + +/* * lwp_getspecific -- * Return lwp-specific data corresponding to the specified key. * @@ -819,7 +836,7 @@ lwp_getspecific(specificdata_key_t key) * Set lwp-specific data corresponding to the specified key. */ void -lwp_setspecific(struct lwp *l, specificdata_key_t key, void *data) +lwp_setspecific(specificdata_key_t key, void *data) { specificdata_setspecific(lwp_specificdata_domain, diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 989e96f19fd..14931dd40bc 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_proc.c,v 1.97 2006/10/09 00:39:06 martin Exp $ */ +/* $NetBSD: kern_proc.c,v 1.98 2006/10/11 04:51:06 thorpej Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -69,7 +69,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.97 2006/10/09 00:39:06 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.98 2006/10/11 04:51:06 thorpej Exp $"); #include "opt_kstack.h" #include "opt_maxuprc.h" @@ -664,8 +664,6 @@ proc_free_mem(struct proc *p) pid_t pid = p->p_pid; struct pid_table *pt; - specificdata_fini(proc_specificdata_domain, &p->p_specdataref); - s = proclist_lock_write(); pt = &pid_table[pid & pid_tbl_mask]; @@ -1295,8 +1293,7 @@ int proc_specific_key_create(specificdata_key_t *keyp, specificdata_dtor_t dtor) { - return (specificdata_key_create(proc_specificdata_domain, - keyp, dtor)); + return (specificdata_key_create(proc_specificdata_domain, keyp, dtor)); } /* @@ -1310,15 +1307,31 @@ proc_specific_key_delete(specificdata_key_t key) specificdata_key_delete(proc_specificdata_domain, key); } +/* + * proc_initspecific -- + * Initialize a proc's specificdata container. + */ void proc_initspecific(struct proc *p) { int error; + error = specificdata_init(proc_specificdata_domain, &p->p_specdataref); KASSERT(error == 0); } /* + * proc_finispecific -- + * Finalize a proc's specificdata container. + */ +void +proc_finispecific(struct proc *p) +{ + + specificdata_fini(proc_specificdata_domain, &p->p_specdataref); +} + +/* * proc_getspecific -- * Return proc-specific data corresponding to the specified key. */ diff --git a/sys/sys/lwp.h b/sys/sys/lwp.h index d1618c2ae98..56bff9adeda 100644 --- a/sys/sys/lwp.h +++ b/sys/sys/lwp.h @@ -1,4 +1,4 @@ -/* $NetBSD: lwp.h,v 1.44 2006/10/11 03:46:42 thorpej Exp $ */ +/* $NetBSD: lwp.h,v 1.45 2006/10/11 04:51:06 thorpej Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -205,6 +205,7 @@ void lwp_update_creds(struct lwp *); int lwp_specific_key_create(specificdata_key_t *, specificdata_dtor_t); void lwp_specific_key_delete(specificdata_key_t); void lwp_initspecific(struct lwp *); +void lwp_finispecific(struct lwp *); void * lwp_getspecific(specificdata_key_t); void lwp_setspecific(specificdata_key_t, void *); #endif /* _KERNEL */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 08a862f6db5..18e9e3c2722 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $NetBSD: proc.h,v 1.229 2006/10/08 22:57:11 christos Exp $ */ +/* $NetBSD: proc.h,v 1.230 2006/10/11 04:51:06 thorpej Exp $ */ /*- * Copyright (c) 1986, 1989, 1991, 1993 @@ -520,6 +520,7 @@ void proc_crmod_enter(struct proc *); int proc_specific_key_create(specificdata_key_t *, specificdata_dtor_t); void proc_specific_key_delete(specificdata_key_t); void proc_initspecific(struct proc *); +void proc_finispecific(struct proc *); void * proc_getspecific(struct proc *, specificdata_key_t); void proc_setspecific(struct proc *, specificdata_key_t, void *); |
