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:
parent
e1f13c8c99
commit
5739c88a75
|
@ -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 *));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue