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
This commit is contained in:
Konstantin Belousov 2007-08-20 12:05:45 +00:00
parent 5114048b63
commit d239bd3ccc
3 changed files with 40 additions and 18 deletions

View File

@ -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 @@ vm_map_findspace(vm_map_t map, vm_offset_t start, vm_size_t length,
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 ]
*

View File

@ -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);

View File

@ -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) {