diff options
author | kib <kib@FreeBSD.org> | 2007-08-20 12:05:45 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2007-08-20 12:05:45 +0000 |
commit | 77766ce03fadc5a3fa344a477dd967530260bb26 (patch) | |
tree | 53ed71997e5c122e87a0dcd8769ef721892ffaa7 /sys/vm | |
parent | e23c502c5b8d2dd20b3e554d80c10f046307cb67 (diff) | |
download | FreeBSD-src-77766ce03fadc5a3fa344a477dd967530260bb26.zip FreeBSD-src-77766ce03fadc5a3fa344a477dd967530260bb26.tar.gz |
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 <tijl ulyssis org>
Reviewed by: alc
Approved by: re (kensmith)
MFC after: 2 weeks
Diffstat (limited to 'sys/vm')
-rw-r--r-- | sys/vm/vm_map.c | 51 | ||||
-rw-r--r-- | sys/vm/vm_map.h | 1 | ||||
-rw-r--r-- | 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 9fe60b7..905201e 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 @@ -1355,22 +1390,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 ] * * Mark the given range as handled by a subordinate map. diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h index de0ab0a..fe50905 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 8744156..fa3e58f 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) { |