summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_exit.c
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2006-05-29 21:28:56 +0000
committertegge <tegge@FreeBSD.org>2006-05-29 21:28:56 +0000
commit0d5f19116220da1e7a0df73c804bebeb5efdf862 (patch)
tree2227714d6a33f215f9677debe94c947b9e3fc437 /sys/kern/kern_exit.c
parentff05f5f32b9783ffa4f05a2b79b7e54056d2f947 (diff)
downloadFreeBSD-src-0d5f19116220da1e7a0df73c804bebeb5efdf862.zip
FreeBSD-src-0d5f19116220da1e7a0df73c804bebeb5efdf862.tar.gz
Close race between vmspace_exitfree() and exit1() and races between
vmspace_exitfree() and vmspace_free() which could result in the same vmspace being freed twice. Factor out part of exit1() into new function vmspace_exit(). Attach to vmspace0 to allow old vmspace to be freed earlier. Add new function, vmspace_acquire_ref(), for obtaining a vmspace reference for a vmspace belonging to another process. Avoid changing vmspace refcount from 0 to 1 since that could also lead to the same vmspace being freed twice. Change vmtotal() and swapout_procs() to use vmspace_acquire_ref(). Reviewed by: alc
Diffstat (limited to 'sys/kern/kern_exit.c')
-rw-r--r--sys/kern/kern_exit.c31
1 files changed, 2 insertions, 29 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index bd44b48..a13c6f3 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -113,14 +113,13 @@ exit1(struct thread *td, int rv)
struct proc *p, *nq, *q;
struct tty *tp;
struct vnode *ttyvp;
- struct vmspace *vm;
struct vnode *vtmp;
#ifdef KTRACE
struct vnode *tracevp;
struct ucred *tracecred;
#endif
struct plimit *plim;
- int locked, refcnt;
+ int locked;
/*
* Drop Giant if caller has it. Eventually we should warn about
@@ -300,33 +299,7 @@ retry:
}
mtx_unlock(&ppeers_lock);
- /* The next two chunks should probably be moved to vmspace_exit. */
- vm = p->p_vmspace;
- /*
- * Release user portion of address space.
- * This releases references to vnodes,
- * which could cause I/O if the file has been unlinked.
- * Need to do this early enough that we can still sleep.
- * Can't free the entire vmspace as the kernel stack
- * may be mapped within that space also.
- *
- * Processes sharing the same vmspace may exit in one order, and
- * get cleaned up by vmspace_exit() in a different order. The
- * last exiting process to reach this point releases as much of
- * the environment as it can, and the last process cleaned up
- * by vmspace_exit() (which decrements exitingcnt) cleans up the
- * remainder.
- */
- atomic_add_int(&vm->vm_exitingcnt, 1);
- do
- refcnt = vm->vm_refcnt;
- while (!atomic_cmpset_int(&vm->vm_refcnt, refcnt, refcnt - 1));
- if (refcnt == 1) {
- shmexit(vm);
- pmap_remove_pages(vmspace_pmap(vm));
- (void) vm_map_remove(&vm->vm_map, vm_map_min(&vm->vm_map),
- vm_map_max(&vm->vm_map));
- }
+ vmspace_exit(td);
sx_xlock(&proctree_lock);
if (SESS_LEADER(p)) {
OpenPOWER on IntegriCloud