Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_map.c
Show First 20 Lines • Show All 1,245 Lines • ▼ Show 20 Lines | |||||
* Recompute the amount of free space following a modified vm_map_entry | * Recompute the amount of free space following a modified vm_map_entry | ||||
* and propagate those values up the tree. Call this function after | * and propagate those values up the tree. Call this function after | ||||
* resizing a map entry in-place by changing the end value, without a | * resizing a map entry in-place by changing the end value, without a | ||||
* call to vm_map_entry_link() or _unlink(). | * call to vm_map_entry_link() or _unlink(). | ||||
* | * | ||||
* The map must be locked, and leaves it so. | * The map must be locked, and leaves it so. | ||||
*/ | */ | ||||
static void | static void | ||||
vm_map_entry_resize_free(vm_map_t map, vm_map_entry_t entry) | vm_map_entry_resize_free(vm_map_t map, vm_map_entry_t entry, size_t grow_amount) | ||||
{ | { | ||||
vm_map_entry_t llist, rlist, root; | vm_map_entry_t llist, rlist, root; | ||||
VM_MAP_ASSERT_LOCKED(map); | VM_MAP_ASSERT_LOCKED(map); | ||||
root = map->root; | root = map->root; | ||||
root = vm_map_splay_split(entry->start, 0, root, &llist, &rlist); | root = vm_map_splay_split(entry->start, 0, root, &llist, &rlist); | ||||
KASSERT(root != NULL, | KASSERT(root != NULL, | ||||
("vm_map_entry_resize_free: resize_free object not mapped")); | ("vm_map_entry_resize_free: resize_free object not mapped")); | ||||
vm_map_splay_findnext(root, &rlist); | vm_map_splay_findnext(root, &rlist); | ||||
root->right = NULL; | root->right = NULL; | ||||
entry->end += grow_amount; | |||||
map->root = vm_map_splay_merge(root, llist, rlist, | map->root = vm_map_splay_merge(root, llist, rlist, | ||||
root->left, root->right); | root->left, root->right); | ||||
VM_MAP_ASSERT_CONSISTENT(map); | VM_MAP_ASSERT_CONSISTENT(map); | ||||
CTR3(KTR_VM, "vm_map_entry_resize_free: map %p, nentries %d, entry %p", map, | CTR3(KTR_VM, "vm_map_entry_resize_free: map %p, nentries %d, entry %p", | ||||
map->nentries, entry); | map, map->nentries, entry); | ||||
} | } | ||||
/* | /* | ||||
* vm_map_lookup_entry: [ internal use only ] | * vm_map_lookup_entry: [ internal use only ] | ||||
* | * | ||||
* Finds the map entry containing (or | * Finds the map entry containing (or | ||||
* immediately preceding) the specified address | * immediately preceding) the specified address | ||||
* in the given map; the entry is returned | * in the given map; the entry is returned | ||||
▲ Show 20 Lines • Show All 203 Lines • ▼ Show 20 Lines | if (prev_entry->inheritance == inheritance && | ||||
prev_entry->protection == prot && | prev_entry->protection == prot && | ||||
prev_entry->max_protection == max && | prev_entry->max_protection == max && | ||||
prev_entry->wired_count == 0) { | prev_entry->wired_count == 0) { | ||||
KASSERT((prev_entry->eflags & MAP_ENTRY_USER_WIRED) == | KASSERT((prev_entry->eflags & MAP_ENTRY_USER_WIRED) == | ||||
0, ("prev_entry %p has incoherent wiring", | 0, ("prev_entry %p has incoherent wiring", | ||||
prev_entry)); | prev_entry)); | ||||
if ((prev_entry->eflags & MAP_ENTRY_GUARD) == 0) | if ((prev_entry->eflags & MAP_ENTRY_GUARD) == 0) | ||||
map->size += end - prev_entry->end; | map->size += end - prev_entry->end; | ||||
prev_entry->end = end; | vm_map_entry_resize_free(map, prev_entry, | ||||
vm_map_entry_resize_free(map, prev_entry); | end - prev_entry->end); | ||||
vm_map_simplify_entry(map, prev_entry); | vm_map_simplify_entry(map, prev_entry); | ||||
return (KERN_SUCCESS); | return (KERN_SUCCESS); | ||||
} | } | ||||
/* | /* | ||||
* If we can extend the object but cannot extend the | * If we can extend the object but cannot extend the | ||||
* map entry, we have to create a new map entry. We | * map entry, we have to create a new map entry. We | ||||
* must bump the ref count on the extended object to | * must bump the ref count on the extended object to | ||||
▲ Show 20 Lines • Show All 2,810 Lines • ▼ Show 20 Lines | if (grow_down) { | ||||
if (gap_entry->start + grow_amount == gap_entry->end) { | if (gap_entry->start + grow_amount == gap_entry->end) { | ||||
gap_start = gap_entry->start; | gap_start = gap_entry->start; | ||||
gap_end = gap_entry->end; | gap_end = gap_entry->end; | ||||
vm_map_entry_delete(map, gap_entry); | vm_map_entry_delete(map, gap_entry); | ||||
gap_deleted = true; | gap_deleted = true; | ||||
} else { | } else { | ||||
MPASS(gap_entry->start < gap_entry->end - grow_amount); | MPASS(gap_entry->start < gap_entry->end - grow_amount); | ||||
gap_entry->end -= grow_amount; | gap_entry->end -= grow_amount; | ||||
vm_map_entry_resize_free(map, gap_entry); | vm_map_entry_resize_free(map, gap_entry, -grow_amount); | ||||
gap_deleted = false; | gap_deleted = false; | ||||
} | } | ||||
rv = vm_map_insert(map, NULL, 0, grow_start, | rv = vm_map_insert(map, NULL, 0, grow_start, | ||||
grow_start + grow_amount, | grow_start + grow_amount, | ||||
stack_entry->protection, stack_entry->max_protection, | stack_entry->protection, stack_entry->max_protection, | ||||
MAP_STACK_GROWS_DOWN); | MAP_STACK_GROWS_DOWN); | ||||
if (rv != KERN_SUCCESS) { | if (rv != KERN_SUCCESS) { | ||||
if (gap_deleted) { | if (gap_deleted) { | ||||
rv1 = vm_map_insert(map, NULL, 0, gap_start, | rv1 = vm_map_insert(map, NULL, 0, gap_start, | ||||
gap_end, VM_PROT_NONE, VM_PROT_NONE, | gap_end, VM_PROT_NONE, VM_PROT_NONE, | ||||
MAP_CREATE_GUARD | MAP_CREATE_STACK_GAP_DN); | MAP_CREATE_GUARD | MAP_CREATE_STACK_GAP_DN); | ||||
MPASS(rv1 == KERN_SUCCESS); | MPASS(rv1 == KERN_SUCCESS); | ||||
} else { | } else | ||||
gap_entry->end += grow_amount; | vm_map_entry_resize_free(map, gap_entry, | ||||
vm_map_entry_resize_free(map, gap_entry); | grow_amount); | ||||
} | } | ||||
} | |||||
} else { | } else { | ||||
grow_start = stack_entry->end; | grow_start = stack_entry->end; | ||||
cred = stack_entry->cred; | cred = stack_entry->cred; | ||||
if (cred == NULL && stack_entry->object.vm_object != NULL) | if (cred == NULL && stack_entry->object.vm_object != NULL) | ||||
cred = stack_entry->object.vm_object->cred; | cred = stack_entry->object.vm_object->cred; | ||||
if (cred != NULL && !swap_reserve_by_cred(grow_amount, cred)) | if (cred != NULL && !swap_reserve_by_cred(grow_amount, cred)) | ||||
rv = KERN_NO_SPACE; | rv = KERN_NO_SPACE; | ||||
/* Grow the underlying object if applicable. */ | /* Grow the underlying object if applicable. */ | ||||
else if (stack_entry->object.vm_object == NULL || | else if (stack_entry->object.vm_object == NULL || | ||||
vm_object_coalesce(stack_entry->object.vm_object, | vm_object_coalesce(stack_entry->object.vm_object, | ||||
stack_entry->offset, | stack_entry->offset, | ||||
(vm_size_t)(stack_entry->end - stack_entry->start), | (vm_size_t)(stack_entry->end - stack_entry->start), | ||||
(vm_size_t)grow_amount, cred != NULL)) { | (vm_size_t)grow_amount, cred != NULL)) { | ||||
if (gap_entry->start + grow_amount == gap_entry->end) | if (gap_entry->start + grow_amount == gap_entry->end) | ||||
vm_map_entry_delete(map, gap_entry); | vm_map_entry_delete(map, gap_entry); | ||||
else | else | ||||
gap_entry->start += grow_amount; | gap_entry->start += grow_amount; | ||||
stack_entry->end += grow_amount; | |||||
map->size += grow_amount; | map->size += grow_amount; | ||||
vm_map_entry_resize_free(map, stack_entry); | vm_map_entry_resize_free(map, stack_entry, grow_amount); | ||||
rv = KERN_SUCCESS; | rv = KERN_SUCCESS; | ||||
} else | } else | ||||
rv = KERN_FAILURE; | rv = KERN_FAILURE; | ||||
} | } | ||||
if (rv == KERN_SUCCESS && is_procstack) | if (rv == KERN_SUCCESS && is_procstack) | ||||
vm->vm_ssize += btoc(grow_amount); | vm->vm_ssize += btoc(grow_amount); | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 507 Lines • Show Last 20 Lines |