diff options
author | tegge <tegge@FreeBSD.org> | 2006-05-29 21:28:56 +0000 |
---|---|---|
committer | tegge <tegge@FreeBSD.org> | 2006-05-29 21:28:56 +0000 |
commit | 0d5f19116220da1e7a0df73c804bebeb5efdf862 (patch) | |
tree | 2227714d6a33f215f9677debe94c947b9e3fc437 /sys/vm/vm_meter.c | |
parent | ff05f5f32b9783ffa4f05a2b79b7e54056d2f947 (diff) | |
download | FreeBSD-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/vm/vm_meter.c')
-rw-r--r-- | sys/vm/vm_meter.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/sys/vm/vm_meter.c b/sys/vm/vm_meter.c index c5d3abc..1665fda 100644 --- a/sys/vm/vm_meter.c +++ b/sys/vm/vm_meter.c @@ -115,6 +115,7 @@ vmtotal(SYSCTL_HANDLER_ARGS) vm_map_t map; int paging; struct thread *td; + struct vmspace *vm; totalp = &total; bzero(totalp, sizeof *totalp); @@ -185,7 +186,10 @@ vmtotal(SYSCTL_HANDLER_ARGS) * Note active objects. */ paging = 0; - map = &p->p_vmspace->vm_map; + vm = vmspace_acquire_ref(p); + if (vm == NULL) + continue; + map = &vm->vm_map; vm_map_lock_read(map); for (entry = map->header.next; entry != &map->header; entry = entry->next) { @@ -198,6 +202,7 @@ vmtotal(SYSCTL_HANDLER_ARGS) VM_OBJECT_UNLOCK(object); } vm_map_unlock_read(map); + vmspace_free(vm); if (paging) totalp->t_pw++; } |