summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_map.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm/vm_map.c')
-rw-r--r--sys/vm/vm_map.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 4b31fb3..96e7411 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -197,7 +197,6 @@ vmspace_zfini(void *mem, int size)
struct vmspace *vm;
vm = (struct vmspace *)mem;
- pmap_release(vmspace_pmap(vm));
vm_map_zfini(&vm->vm_map, sizeof(vm->vm_map));
}
@@ -208,8 +207,8 @@ vmspace_zinit(void *mem, int size, int flags)
vm = (struct vmspace *)mem;
+ vm->vm_map.pmap = NULL;
(void)vm_map_zinit(&vm->vm_map, sizeof(vm->vm_map), flags);
- pmap_pinit(vmspace_pmap(vm));
return (0);
}
@@ -272,6 +271,10 @@ vmspace_alloc(min, max)
struct vmspace *vm;
vm = uma_zalloc(vmspace_zone, M_WAITOK);
+ if (vm->vm_map.pmap == NULL && !pmap_pinit(vmspace_pmap(vm))) {
+ uma_zfree(vmspace_zone, vm);
+ return (NULL);
+ }
CTR1(KTR_VM, "vmspace_alloc: %p", vm);
_vm_map_init(&vm->vm_map, min, max);
vm->vm_map.pmap = vmspace_pmap(vm); /* XXX */
@@ -321,6 +324,12 @@ vmspace_dofree(struct vmspace *vm)
(void)vm_map_remove(&vm->vm_map, vm->vm_map.min_offset,
vm->vm_map.max_offset);
+ /*
+ * XXX Comment out the pmap_release call for now. The
+ * vmspace_zone is marked as UMA_ZONE_NOFREE, and bugs cause
+ * pmap.resident_count to be != 0 on exit sometimes.
+ */
+/* pmap_release(vmspace_pmap(vm)); */
uma_zfree(vmspace_zone, vm);
}
@@ -2584,6 +2593,8 @@ vmspace_fork(struct vmspace *vm1)
vm_map_lock(old_map);
vm2 = vmspace_alloc(old_map->min_offset, old_map->max_offset);
+ if (vm2 == NULL)
+ goto unlock_and_return;
vm2->vm_taddr = vm1->vm_taddr;
vm2->vm_daddr = vm1->vm_daddr;
vm2->vm_maxsaddr = vm1->vm_maxsaddr;
@@ -2675,7 +2686,7 @@ vmspace_fork(struct vmspace *vm1)
}
old_entry = old_entry->next;
}
-
+unlock_and_return:
vm_map_unlock(old_map);
return (vm2);
@@ -3003,13 +3014,15 @@ Retry:
* Unshare the specified VM space for exec. If other processes are
* mapped to it, then create a new one. The new vmspace is null.
*/
-void
+int
vmspace_exec(struct proc *p, vm_offset_t minuser, vm_offset_t maxuser)
{
struct vmspace *oldvmspace = p->p_vmspace;
struct vmspace *newvmspace;
newvmspace = vmspace_alloc(minuser, maxuser);
+ if (newvmspace == NULL)
+ return (ENOMEM);
newvmspace->vm_swrss = oldvmspace->vm_swrss;
/*
* This code is written like this for prototype purposes. The
@@ -3024,27 +3037,31 @@ vmspace_exec(struct proc *p, vm_offset_t minuser, vm_offset_t maxuser)
if (p == curthread->td_proc) /* XXXKSE ? */
pmap_activate(curthread);
vmspace_free(oldvmspace);
+ return (0);
}
/*
* Unshare the specified VM space for forcing COW. This
* is called by rfork, for the (RFMEM|RFPROC) == 0 case.
*/
-void
+int
vmspace_unshare(struct proc *p)
{
struct vmspace *oldvmspace = p->p_vmspace;
struct vmspace *newvmspace;
if (oldvmspace->vm_refcnt == 1)
- return;
+ return (0);
newvmspace = vmspace_fork(oldvmspace);
+ if (newvmspace == NULL)
+ return (ENOMEM);
PROC_VMSPACE_LOCK(p);
p->p_vmspace = newvmspace;
PROC_VMSPACE_UNLOCK(p);
if (p == curthread->td_proc) /* XXXKSE ? */
pmap_activate(curthread);
vmspace_free(oldvmspace);
+ return (0);
}
/*
OpenPOWER on IntegriCloud