diff options
author | kib <kib@FreeBSD.org> | 2009-02-08 20:39:17 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2009-02-08 20:39:17 +0000 |
commit | ae7c4cfa1196d4f42be0f573c827a5dd2d385af9 (patch) | |
tree | 090d271c805930a672a18b2da7d0cd0774d02586 /sys/vm/vm_map.c | |
parent | 9a341e28ebd8cb82b35c8eeb849a7607597d399e (diff) | |
download | FreeBSD-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.c | 40 |
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); } |