Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_map.c
Show First 20 Lines • Show All 1,635 Lines • ▼ Show 20 Lines | |||||
* Returns: starting address if sufficient space, | * Returns: starting address if sufficient space, | ||||
* vm_map_max(map)-length+1 if insufficient space. | * vm_map_max(map)-length+1 if insufficient space. | ||||
*/ | */ | ||||
vm_offset_t | vm_offset_t | ||||
vm_map_findspace(vm_map_t map, vm_offset_t start, vm_size_t length) | vm_map_findspace(vm_map_t map, vm_offset_t start, vm_size_t length) | ||||
{ | { | ||||
vm_map_entry_t llist, rlist, root, y; | vm_map_entry_t llist, rlist, root, y; | ||||
vm_size_t left_length; | vm_size_t left_length; | ||||
vm_offset_t gap_end; | |||||
/* | /* | ||||
* Request must fit within min/max VM address and must avoid | * Request must fit within min/max VM address and must avoid | ||||
* address wrap. | * address wrap. | ||||
*/ | */ | ||||
start = MAX(start, vm_map_min(map)); | start = MAX(start, vm_map_min(map)); | ||||
if (start + length > vm_map_max(map) || start + length < start) | if (start >= vm_map_max(map) || length > vm_map_max(map) - start) | ||||
return (vm_map_max(map) - length + 1); | return (vm_map_max(map) - length + 1); | ||||
/* Empty tree means wide open address space. */ | /* Empty tree means wide open address space. */ | ||||
if (map->root == NULL) | if (map->root == NULL) | ||||
return (start); | return (start); | ||||
/* | /* | ||||
* After splay, if start comes before root node, then there | * After splay_split, if start is within an entry, push it to the start | ||||
* must be a gap from start to the root. | * of the following gap. If rlist is at the end of the gap containing | ||||
* start, save the end of that gap in gap_end to see if the gap is big | |||||
* enough; otherwise set gap_end to start skip gap-checking and move | |||||
* directly to a search of the right subtree. | |||||
*/ | */ | ||||
root = vm_map_splay_split(map, start, length, &llist, &rlist); | root = vm_map_splay_split(map, start, length, &llist, &rlist); | ||||
if (root != NULL) | gap_end = rlist->start; | ||||
if (root != NULL) { | |||||
start = root->end; | start = root->end; | ||||
else if (rlist != &map->header) { | if (root->right != NULL) | ||||
gap_end = start; | |||||
} else if (rlist != &map->header) { | |||||
root = rlist; | root = rlist; | ||||
rlist = root->left; | rlist = root->left; | ||||
root->left = NULL; | root->left = NULL; | ||||
} else { | } else { | ||||
root = llist; | root = llist; | ||||
llist = root->right; | llist = root->right; | ||||
root->right = NULL; | root->right = NULL; | ||||
} | } | ||||
vm_map_splay_merge(map, root, llist, rlist); | vm_map_splay_merge(map, root, llist, rlist); | ||||
VM_MAP_ASSERT_CONSISTENT(map); | VM_MAP_ASSERT_CONSISTENT(map); | ||||
if (start + length <= root->start) | if (length <= gap_end - start) | ||||
return (start); | return (start); | ||||
/* | |||||
* Root is the last node that might begin its gap before | |||||
* start, and this is the last comparison where address | |||||
* wrap might be a problem. | |||||
*/ | |||||
if (root->right == NULL && | |||||
start + length <= vm_map_max(map)) | |||||
return (start); | |||||
/* With max_free, can immediately tell if no solution. */ | /* With max_free, can immediately tell if no solution. */ | ||||
if (root->right == NULL || length > root->right->max_free) | if (root->right == NULL || length > root->right->max_free) | ||||
return (vm_map_max(map) - length + 1); | return (vm_map_max(map) - length + 1); | ||||
/* | /* | ||||
* Splay for the least large-enough gap in the right subtree. | * Splay for the least large-enough gap in the right subtree. | ||||
*/ | */ | ||||
llist = rlist = &map->header; | llist = rlist = &map->header; | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | vm_map_alignspace(vm_map_t map, vm_object_t object, vm_ooffset_t offset, | ||||
vm_offset_t *addr, vm_size_t length, vm_offset_t max_addr, | vm_offset_t *addr, vm_size_t length, vm_offset_t max_addr, | ||||
vm_offset_t alignment) | vm_offset_t alignment) | ||||
{ | { | ||||
vm_offset_t aligned_addr, free_addr; | vm_offset_t aligned_addr, free_addr; | ||||
VM_MAP_ASSERT_LOCKED(map); | VM_MAP_ASSERT_LOCKED(map); | ||||
free_addr = *addr; | free_addr = *addr; | ||||
KASSERT(free_addr == vm_map_findspace(map, free_addr, length), | KASSERT(free_addr == vm_map_findspace(map, free_addr, length), | ||||
("caller failed to provide space %d at address %p", | ("caller failed to provide space %#jx at address %p", | ||||
(int)length, (void*)free_addr)); | (uintmax_t)length, (void *)free_addr)); | ||||
for (;;) { | for (;;) { | ||||
/* | /* | ||||
* At the start of every iteration, the free space at address | * At the start of every iteration, the free space at address | ||||
* "*addr" is at least "length" bytes. | * "*addr" is at least "length" bytes. | ||||
*/ | */ | ||||
if (alignment == 0) | if (alignment == 0) | ||||
pmap_align_superpage(object, offset, addr, length); | pmap_align_superpage(object, offset, addr, length); | ||||
else if ((*addr & (alignment - 1)) != 0) { | else if ((*addr & (alignment - 1)) != 0) { | ||||
▲ Show 20 Lines • Show All 3,108 Lines • Show Last 20 Lines |