Index: kern/kern_exit.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_exit.c,v retrieving revision 1.146 retrieving revision 1.147 diff -u -r1.146 -r1.147 --- kern/kern_exit.c 5 Jan 2002 21:47:58 -0000 1.146 +++ kern/kern_exit.c 5 Feb 2002 21:23:05 -0000 1.147 @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 - * $FreeBSD: src/sys/kern/kern_exit.c,v 1.146 2002/01/05 21:47:58 dwmalone Exp $ + * $FreeBSD: src/sys/kern/kern_exit.c,v 1.147 2002/02/05 21:23:05 alfred Exp $ */ #include "opt_compat.h" @@ -217,13 +217,14 @@ * Can't free the entire vmspace as the kernel stack * may be mapped within that space also. */ - if (vm->vm_refcnt == 1) { + if (--vm->vm_refcnt == 0) { if (vm->vm_shm) shmexit(p); pmap_remove_pages(vmspace_pmap(vm), VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); (void) vm_map_remove(&vm->vm_map, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); + vm->vm_freer = p; } PROC_LOCK(p); @@ -400,8 +401,8 @@ /* * Finally, call machine-dependent code to release the remaining * resources including address space, the kernel stack and pcb. - * The address space is released by "vmspace_free(p->p_vmspace)" - * in vm_waitproc(); + * The address space is released by "vmspace_exitfree(p)" in + * vm_waitproc(). */ cpu_exit(td); Index: vm/vm_extern.h =================================================================== RCS file: /home/ncvs/src/sys/vm/vm_extern.h,v retrieving revision 1.50 retrieving revision 1.51 diff -u -r1.50 -r1.51 --- vm/vm_extern.h 20 Oct 2001 13:10:43 -0000 1.50 +++ vm/vm_extern.h 5 Feb 2002 21:23:05 -0000 1.51 @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)vm_extern.h 8.2 (Berkeley) 1/12/94 - * $FreeBSD: src/sys/vm/vm_extern.h,v 1.50 2001/10/20 13:10:43 iedowse Exp $ + * $FreeBSD: src/sys/vm/vm_extern.h,v 1.51 2002/02/05 21:23:05 alfred Exp $ */ #ifndef _VM_EXTERN_H_ @@ -90,6 +90,7 @@ void vmspace_exec __P((struct proc *)); void vmspace_unshare __P((struct proc *)); void vmspace_free __P((struct vmspace *)); +void vmspace_exitfree __P((struct proc *)); void vnode_pager_setsize __P((struct vnode *, vm_ooffset_t)); void vslock __P((caddr_t, u_int)); void vsunlock __P((caddr_t, u_int)); Index: vm/vm_glue.c =================================================================== RCS file: /home/ncvs/src/sys/vm/vm_glue.c,v retrieving revision 1.122 retrieving revision 1.123 diff -u -r1.122 -r1.123 --- vm/vm_glue.c 17 Jan 2002 16:46:26 -0000 1.122 +++ vm/vm_glue.c 5 Feb 2002 21:23:05 -0000 1.123 @@ -59,7 +59,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $FreeBSD: src/sys/vm/vm_glue.c,v 1.122 2002/01/17 16:46:26 bde Exp $ + * $FreeBSD: src/sys/vm/vm_glue.c,v 1.123 2002/02/05 21:23:05 alfred Exp $ */ #include "opt_vm.h" @@ -305,7 +305,7 @@ pmap_dispose_proc(p); /* drop per-process resources */ FOREACH_THREAD_IN_PROC(p, td) pmap_dispose_thread(td); - vmspace_free(p->p_vmspace); /* and clean-out the vmspace */ + vmspace_exitfree(p); /* and clean-out the vmspace */ } /* Index: vm/vm_map.c =================================================================== RCS file: /home/ncvs/src/sys/vm/vm_map.c,v retrieving revision 1.211 retrieving revision 1.212 diff -u -r1.211 -r1.212 --- vm/vm_map.c 31 Oct 2001 03:06:32 -0000 1.211 +++ vm/vm_map.c 5 Feb 2002 21:23:05 -0000 1.212 @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $FreeBSD: src/sys/vm/vm_map.c,v 1.211 2001/10/31 03:06:32 dillon Exp $ + * $FreeBSD: src/sys/vm/vm_map.c,v 1.212 2002/02/05 21:23:05 alfred Exp $ */ /* @@ -172,6 +172,7 @@ vm->vm_map.pmap = vmspace_pmap(vm); /* XXX */ vm->vm_refcnt = 1; vm->vm_shm = NULL; + vm->vm_freer = NULL; return (vm); } @@ -189,6 +190,24 @@ vm_object_init2(); } +static __inline void +vmspace_dofree( struct vmspace *vm) +{ + CTR1(KTR_VM, "vmspace_free: %p", vm); + /* + * Lock the map, to wait out all other references to it. + * Delete all of the mappings and pages they hold, then call + * the pmap module to reclaim anything left. + */ + vm_map_lock(&vm->vm_map); + (void) vm_map_delete(&vm->vm_map, vm->vm_map.min_offset, + vm->vm_map.max_offset); + vm_map_unlock(&vm->vm_map); + pmap_release(vmspace_pmap(vm)); + vm_map_destroy(&vm->vm_map); + zfree(vmspace_zone, vm); +} + void vmspace_free(struct vmspace *vm) { @@ -197,23 +216,17 @@ if (vm->vm_refcnt == 0) panic("vmspace_free: attempt to free already freed vmspace"); - if (--vm->vm_refcnt == 0) { + if (--vm->vm_refcnt == 0) + vmspace_dofree(vm); +} + +void +vmspace_exitfree(struct proc *p) +{ + GIANT_REQUIRED; - CTR1(KTR_VM, "vmspace_free: %p", vm); - /* - * Lock the map, to wait out all other references to it. - * Delete all of the mappings and pages they hold, then call - * the pmap module to reclaim anything left. - */ - vm_map_lock(&vm->vm_map); - (void) vm_map_delete(&vm->vm_map, vm->vm_map.min_offset, - vm->vm_map.max_offset); - vm_map_unlock(&vm->vm_map); - - pmap_release(vmspace_pmap(vm)); - vm_map_destroy(&vm->vm_map); - zfree(vmspace_zone, vm); - } + if (p == p->p_vmspace->vm_freer) + vmspace_dofree(p->p_vmspace); } /* @@ -2317,7 +2330,7 @@ vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset); bcopy(&vm1->vm_startcopy, &vm2->vm_startcopy, - (caddr_t) (vm1 + 1) - (caddr_t) &vm1->vm_startcopy); + (caddr_t) &vm1->vm_endcopy - (caddr_t) &vm1->vm_startcopy); new_map = &vm2->vm_map; /* XXX */ new_map->timestamp = 1; Index: vm/vm_map.h =================================================================== RCS file: /home/ncvs/src/sys/vm/vm_map.h,v retrieving revision 1.68 retrieving revision 1.69 diff -u -r1.68 -r1.69 --- vm/vm_map.h 31 Oct 2001 03:06:32 -0000 1.68 +++ vm/vm_map.h 5 Feb 2002 21:23:05 -0000 1.69 @@ -61,7 +61,7 @@ * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * - * $FreeBSD: src/sys/vm/vm_map.h,v 1.68 2001/10/31 03:06:32 dillon Exp $ + * $FreeBSD: src/sys/vm/vm_map.h,v 1.69 2002/02/05 21:23:05 alfred Exp $ */ /* @@ -188,6 +188,8 @@ caddr_t vm_daddr; /* user virtual address of data XXX */ caddr_t vm_maxsaddr; /* user VA at max stack growth */ caddr_t vm_minsaddr; /* user VA at max stack growth */ +#define vm_endcopy vm_freer + struct proc *vm_freer; /* vm freed on whose behalf */ }; #ifdef _KERNEL