Implement address space sharing (by keeping ref counts on the vmspace

structure).  Many thanks to Chuck Cranor for debugging assistence.
This commit is contained in:
thorpej 1998-01-03 02:53:00 +00:00
parent e1f13c8c99
commit 5739c88a75
3 changed files with 104 additions and 34 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: vm_extern.h,v 1.28 1997/12/31 07:47:41 thorpej Exp $ */
/* $NetBSD: vm_extern.h,v 1.29 1998/01/03 02:53:00 thorpej Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -119,7 +119,7 @@ void vm_fault_copy_entry __P((vm_map_t,
vm_map_t, vm_map_entry_t, vm_map_entry_t));
void vm_fault_unwire __P((vm_map_t, vm_offset_t, vm_offset_t));
int vm_fault_wire __P((vm_map_t, vm_offset_t, vm_offset_t));
void vm_fork __P((struct proc *, struct proc *));
void vm_fork __P((struct proc *, struct proc *, boolean_t));
int vm_inherit __P((vm_map_t,
vm_offset_t, vm_size_t, vm_inherit_t));
void vm_init_limits __P((struct proc *));
@ -134,6 +134,8 @@ struct vmspace *vmspace_alloc __P((vm_offset_t, vm_offset_t, int));
struct vmspace *vmspace_fork __P((struct vmspace *));
void vmspace_exec __P((struct proc *));
void vmspace_free __P((struct vmspace *));
void vmspace_share __P((struct proc *, struct proc *));
void vmspace_unshare __P((struct proc *));
void vmtotal __P((struct vmtotal *));
void vnode_pager_setsize __P((struct vnode *, u_quad_t));
void vnode_pager_sync __P((struct mount *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: vm_glue.c,v 1.68 1997/06/19 20:54:48 pk Exp $ */
/* $NetBSD: vm_glue.c,v 1.69 1998/01/03 02:53:02 thorpej Exp $ */
/*
* Copyright (c) 1991, 1993
@ -202,26 +202,20 @@ vsunlock(addr, len)
* after cpu_fork returns.
*/
void
vm_fork(p1, p2)
vm_fork(p1, p2, shared)
register struct proc *p1, *p2;
boolean_t shared;
{
register struct user *up;
vm_offset_t addr;
#if defined(i386) || defined(pc532)
/*
* avoid copying any of the parent's pagetables or other per-process
* objects that reside in the map by marking all of them non-inheritable
* Share the address space if we've been directed to.
*/
(void)vm_map_inherit(&p1->p_vmspace->vm_map,
VM_MAXUSER_ADDRESS, VM_MAX_ADDRESS, VM_INHERIT_NONE);
#endif
p2->p_vmspace = vmspace_fork(p1->p_vmspace);
#ifdef SYSVSHM
if (p1->p_vmspace->vm_shm)
shmfork(p1, p2);
#endif
if (shared == TRUE)
vmspace_share(p1, p2);
else
p2->p_vmspace = vmspace_fork(p1->p_vmspace);
#if !defined(vax)
/*
@ -260,17 +254,6 @@ vm_fork(p1, p2)
((caddr_t)&up->u_stats.pstat_endcopy -
(caddr_t)&up->u_stats.pstat_startcopy));
#if defined(i386) || defined(pc532)
{ vm_offset_t addr = VM_MAXUSER_ADDRESS; struct vm_map *vp;
/* ream out old pagetables and kernel stack */
vp = &p2->p_vmspace->vm_map;
(void)vm_deallocate(vp, addr, VM_MAX_ADDRESS - addr);
(void)vm_allocate(vp, &addr, VM_MAX_ADDRESS - addr, FALSE);
(void)vm_map_inherit(vp, addr, VM_MAX_ADDRESS, VM_INHERIT_NONE);
}
#endif
/*
* cpu_fork will copy and update the kernel stack and pcb,
* and make the child ready to run. The child will exit

View File

@ -1,4 +1,4 @@
/* $NetBSD: vm_map.c,v 1.30 1997/12/31 07:47:42 thorpej Exp $ */
/* $NetBSD: vm_map.c,v 1.31 1998/01/03 02:53:04 thorpej Exp $ */
/*
* Copyright (c) 1991, 1993
@ -71,6 +71,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#ifdef SYSVSHM
#include <sys/shm.h>
@ -205,6 +206,36 @@ vmspace_alloc(min, max, pageable)
return (vm);
}
/*
* Make p1 and p2 share address space.
*/
void
vmspace_share(p1, p2)
struct proc *p1, *p2;
{
p2->p_vmspace = p1->p_vmspace;
p1->p_vmspace->vm_refcnt++;
}
/*
* Make p not share its address space.
*/
void
vmspace_unshare(p)
struct proc *p;
{
struct vmspace *nvm, *ovm = p->p_vmspace;
if (ovm->vm_refcnt == 1)
return;
nvm = vmspace_fork(ovm);
p->p_vmspace = nvm;
pmap_activate(p);
vmspace_free(ovm);
}
/*
* Perform operations on VM space that need to happen during exec.
*/
@ -212,20 +243,49 @@ void
vmspace_exec(p)
struct proc *p;
{
struct vmspace *ovm = p->p_vmspace;
struct vmspace *nvm, *ovm = p->p_vmspace;
vm_map_t map = &ovm->vm_map;
#ifdef sparc
/* XXX cgd 960926: the sparc #ifdef should be a MD hook */
kill_user_windows(p); /* before stack addresses go away */
#endif
/* Kill shared memory and unmap old program. */
if (ovm->vm_refcnt == 1) {
/*
* Destroy this process's VM space.
*/
#ifdef SYSVSHM
if (ovm->vm_shm)
shmexit(p);
/* Kill shared memory. */
if (ovm->vm_shm)
shmexit(ovm);
#endif
vm_deallocate(map, VM_MIN_ADDRESS,
VM_MAXUSER_ADDRESS - VM_MIN_ADDRESS);
/* Unmap old program. */
vm_deallocate(map, VM_MIN_ADDRESS,
VM_MAXUSER_ADDRESS - VM_MIN_ADDRESS);
} else {
/*
* This address space is being shared. We must
* create a new one to avoid disrupting other
* processes that are using it. Since we would
* immediately unmap the entire address space,
* we do minimal work here.
*/
nvm = vmspace_alloc(map->min_offset, map->max_offset,
map->entries_pageable);
#if defined(i386) || defined(pc532) /* XXX XXX XXX */
/* Allocate page table space. */
{ vm_offset_t addr = VM_MAXUSER_ADDRESS;
(void) vm_allocate(&nvm->vm_map, &addr, VM_MAX_ADDRESS - addr,
FALSE);
(void) vm_map_inherit(&nvm->vm_map, addr, VM_MAX_ADDRESS,
VM_INHERIT_NONE);
}
#endif
p->p_vmspace = nvm;
pmap_activate(p);
vmspace_free(ovm);
}
}
void
@ -2165,6 +2225,17 @@ vmspace_fork(vm1)
vm_map_entry_t new_entry;
pmap_t new_pmap;
#if defined(i386) || defined(pc532) /* XXX XXX XXX */
/*
* Avoid copying any of the parent's page tables or other
* per-process objects that reside in the map by marking
* all of them non-inheritable.
*/
(void) vm_map_inherit(old_map, VM_MAXUSER_ADDRESS, VM_MAX_ADDRESS,
VM_INHERIT_NONE);
#endif
vm_map_lock(old_map);
vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset,
@ -2297,6 +2368,20 @@ vmspace_fork(vm1)
new_map->size = old_map->size;
vm_map_unlock(old_map);
#if defined(i386) || defined(pc532) /* XXX XXX XXX */
/* Allocate page table space. */
{ vm_offset_t addr = VM_MAXUSER_ADDRESS;
(void) vm_allocate(new_map, &addr, VM_MAX_ADDRESS - addr, FALSE);
(void) vm_map_inherit(new_map, addr, VM_MAX_ADDRESS,
VM_INHERIT_NONE);
}
#endif
#ifdef SYSVSHM
if (vm1->vm_shm)
shmfork(vm1, vm2);
#endif
return(vm2);
}