summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_map.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-02-08 20:39:17 +0000
committerkib <kib@FreeBSD.org>2009-02-08 20:39:17 +0000
commitae7c4cfa1196d4f42be0f573c827a5dd2d385af9 (patch)
tree090d271c805930a672a18b2da7d0cd0774d02586 /sys/vm/vm_map.c
parent9a341e28ebd8cb82b35c8eeb849a7607597d399e (diff)
downloadFreeBSD-src-ae7c4cfa1196d4f42be0f573c827a5dd2d385af9.zip
FreeBSD-src-ae7c4cfa1196d4f42be0f573c827a5dd2d385af9.tar.gz
Do not call vm_object_deallocate() from vm_map_delete(), because we
hold the map lock there, and might need the vnode lock for OBJT_VNODE objects. Postpone object deallocation until caller of vm_map_delete() drops the map lock. Link the map entries to be freed into the freelist, that is released by the new helper function vm_map_entry_free_freelist(). Reviewed by: tegge, alc Tested by: pho
Diffstat (limited to 'sys/vm/vm_map.c')
-rw-r--r--sys/vm/vm_map.c40
1 files changed, 32 insertions, 8 deletions
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 281f436..43dad2b 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -1261,16 +1261,19 @@ vm_map_fixed(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
vm_offset_t start, vm_size_t length, vm_prot_t prot,
vm_prot_t max, int cow)
{
+ vm_map_entry_t freelist;
vm_offset_t end;
int result;
- vm_map_lock(map);
end = start + length;
+ freelist = NULL;
+ vm_map_lock(map);
VM_MAP_RANGE_CHECK(map, start, end);
- (void) vm_map_delete(map, start, end);
+ (void) vm_map_delete(map, start, end, &freelist);
result = vm_map_insert(map, object, offset, start, end, prot,
max, cow);
vm_map_unlock(map);
+ vm_map_entry_free_freelist(map, freelist);
return (result);
}
@@ -2392,6 +2395,23 @@ vm_map_entry_unwire(vm_map_t map, vm_map_entry_t entry)
entry->wired_count = 0;
}
+void
+vm_map_entry_free_freelist(vm_map_t map, vm_map_entry_t freelist)
+{
+ vm_map_entry_t e;
+ vm_object_t object;
+
+ while (freelist != NULL) {
+ e = freelist;
+ freelist = freelist->next;
+ if ((e->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) {
+ object = e->object.vm_object;
+ vm_object_deallocate(object);
+ }
+ vm_map_entry_dispose(map, e);
+ }
+}
+
/*
* vm_map_entry_delete: [ internal use only ]
*
@@ -2424,10 +2444,8 @@ vm_map_entry_delete(vm_map_t map, vm_map_entry_t entry)
object->size = offidxstart;
}
VM_OBJECT_UNLOCK(object);
- vm_object_deallocate(object);
- }
-
- vm_map_entry_dispose(map, entry);
+ } else
+ entry->object.vm_object = NULL;
}
/*
@@ -2437,7 +2455,8 @@ vm_map_entry_delete(vm_map_t map, vm_map_entry_t entry)
* map.
*/
int
-vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end)
+vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end,
+ vm_map_entry_t *freelist)
{
vm_map_entry_t entry;
vm_map_entry_t first_entry;
@@ -2514,6 +2533,8 @@ vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end)
* modify bits will be set in the wrong object!)
*/
vm_map_entry_delete(map, entry);
+ entry->next = *freelist;
+ *freelist = entry;
entry = next;
}
return (KERN_SUCCESS);
@@ -2528,12 +2549,15 @@ vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end)
int
vm_map_remove(vm_map_t map, vm_offset_t start, vm_offset_t end)
{
+ vm_map_entry_t freelist;
int result;
+ freelist = NULL;
vm_map_lock(map);
VM_MAP_RANGE_CHECK(map, start, end);
- result = vm_map_delete(map, start, end);
+ result = vm_map_delete(map, start, end, &freelist);
vm_map_unlock(map);
+ vm_map_entry_free_freelist(map, freelist);
return (result);
}
OpenPOWER on IntegriCloud