From 77766ce03fadc5a3fa344a477dd967530260bb26 Mon Sep 17 00:00:00 2001 From: kib Date: Mon, 20 Aug 2007 12:05:45 +0000 Subject: [PATCH] Do not drop vm_map lock between doing vm_map_remove() and vm_map_insert(). For this, introduce vm_map_fixed() that does that for MAP_FIXED case. Dropping the lock allowed for parallel thread to occupy the freed space. Reported by: Tijl Coosemans Reviewed by: alc Approved by: re (kensmith) MFC after: 2 weeks --- sys/vm/vm_map.c | 51 +++++++++++++++++++++++++++++++++--------------- sys/vm/vm_map.h | 1 + sys/vm/vm_mmap.c | 6 ++++-- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 9fe60b74481c..905201ee46bb 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -155,6 +155,22 @@ static void vmspace_zdtor(void *mem, int size, void *arg); #define PROC_VMSPACE_LOCK(p) do { } while (0) #define PROC_VMSPACE_UNLOCK(p) do { } while (0) +/* + * VM_MAP_RANGE_CHECK: [ internal use only ] + * + * Asserts that the starting and ending region + * addresses fall within the valid range of the map. + */ +#define VM_MAP_RANGE_CHECK(map, start, end) \ + { \ + if (start < vm_map_min(map)) \ + start = vm_map_min(map); \ + if (end > vm_map_max(map)) \ + end = vm_map_max(map); \ + if (start > end) \ + start = end; \ + } + void vm_map_startup(void) { @@ -1145,6 +1161,25 @@ found: return (0); } +int +vm_map_fixed(vm_map_t map, vm_object_t object, vm_ooffset_t offset, + vm_offset_t *addr /* IN/OUT */, vm_size_t length, vm_prot_t prot, + vm_prot_t max, int cow) +{ + vm_offset_t start, end; + int result; + + start = *addr; + vm_map_lock(map); + end = start + length; + VM_MAP_RANGE_CHECK(map, start, end); + (void) vm_map_delete(map, start, end); + result = vm_map_insert(map, object, offset, start, end, prot, + max, cow); + vm_map_unlock(map); + return (result); +} + /* * vm_map_find finds an unallocated region in the target address * map with the given length. The search is defined to be @@ -1354,22 +1389,6 @@ _vm_map_clip_end(vm_map_t map, vm_map_entry_t entry, vm_offset_t end) } } -/* - * VM_MAP_RANGE_CHECK: [ internal use only ] - * - * Asserts that the starting and ending region - * addresses fall within the valid range of the map. - */ -#define VM_MAP_RANGE_CHECK(map, start, end) \ - { \ - if (start < vm_map_min(map)) \ - start = vm_map_min(map); \ - if (end > vm_map_max(map)) \ - end = vm_map_max(map); \ - if (start > end) \ - start = end; \ - } - /* * vm_map_submap: [ kernel use only ] * diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index de0ab0ab954b..fe5090589f32 100644 --- a/sys/vm/vm_map.h +++ b/sys/vm/vm_map.h @@ -333,6 +333,7 @@ boolean_t vm_map_check_protection (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t vm_map_t vm_map_create(pmap_t, vm_offset_t, vm_offset_t); int vm_map_delete (vm_map_t, vm_offset_t, vm_offset_t); int vm_map_find (vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, boolean_t, vm_prot_t, vm_prot_t, int); +int vm_map_fixed (vm_map_t, vm_object_t, vm_ooffset_t, vm_offset_t *, vm_size_t, vm_prot_t, vm_prot_t, int); int vm_map_findspace (vm_map_t, vm_offset_t, vm_size_t, vm_offset_t *); int vm_map_inherit (vm_map_t, vm_offset_t, vm_offset_t, vm_inherit_t); void vm_map_init (struct vm_map *, vm_offset_t, vm_offset_t); diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c index 87441560e00a..fa3e58f9ca70 100644 --- a/sys/vm/vm_mmap.c +++ b/sys/vm/vm_mmap.c @@ -1341,7 +1341,6 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, if (*addr != trunc_page(*addr)) return (EINVAL); fitit = FALSE; - (void) vm_map_remove(map, *addr, *addr + size); } /* * Lookup/allocate object. @@ -1400,8 +1399,11 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot, if (flags & MAP_STACK) rv = vm_map_stack(map, *addr, size, prot, maxprot, docow | MAP_STACK_GROWS_DOWN); + else if (fitit) + rv = vm_map_find(map, object, foff, addr, size, TRUE, + prot, maxprot, docow); else - rv = vm_map_find(map, object, foff, addr, size, fitit, + rv = vm_map_fixed(map, object, foff, addr, size, prot, maxprot, docow); if (rv != KERN_SUCCESS) {