summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2007-08-20 12:05:45 +0000
committerkib <kib@FreeBSD.org>2007-08-20 12:05:45 +0000
commit77766ce03fadc5a3fa344a477dd967530260bb26 (patch)
tree53ed71997e5c122e87a0dcd8769ef721892ffaa7 /sys
parente23c502c5b8d2dd20b3e554d80c10f046307cb67 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/vm/vm_map.c51
-rw-r--r--sys/vm/vm_map.h1
-rw-r--r--sys/vm/vm_mmap.c6
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) {
OpenPOWER on IntegriCloud