Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_map.c
Context not available. | |||||
{ | { | ||||
map->header.next = map->header.prev = &map->header; | map->header.next = map->header.prev = &map->header; | ||||
map->header.left = map->header.right = NULL; | |||||
map->header.adj_free = max - min; | |||||
map->header.max_free = map->header.adj_free; | |||||
map->needs_wakeup = FALSE; | map->needs_wakeup = FALSE; | ||||
map->system_map = 0; | map->system_map = 0; | ||||
map->pmap = pmap; | map->pmap = pmap; | ||||
map->header.end = min; | map->header.end = min; | ||||
map->header.start = max; | map->header.start = max; | ||||
map->flags = 0; | map->flags = 0; | ||||
map->root = NULL; | map->root = &map->header; | ||||
map->timestamp = 0; | map->timestamp = 0; | ||||
map->busy = 0; | map->busy = 0; | ||||
} | } | ||||
Context not available. | |||||
} | } | ||||
/* | /* | ||||
* vm_map_entry_splay: | * vm_map_splay: | ||||
* | * | ||||
* The Sleator and Tarjan top-down splay algorithm with the | * The Sleator and Tarjan top-down splay algorithm with the | ||||
* following variation. Max_free must be computed bottom-up, so | * following variation. Max_free must be computed bottom-up, so | ||||
Context not available. | |||||
* the pointers and compute max_free. The time bound is O(log n) | * the pointers and compute max_free. The time bound is O(log n) | ||||
* amortized. | * amortized. | ||||
* | * | ||||
* The new root is the vm_map_entry containing "addr", or else an | * The new root is the vm_map_entry containing "addr", or else | ||||
* adjacent entry (lower or higher) if addr is not in the tree. | * the next lower entry if addr is not in the tree. | ||||
* | * | ||||
* The map must be locked, and leaves it so. | * The map must be locked, and leaves it so. | ||||
* | * | ||||
* Returns: the new root. | |||||
*/ | */ | ||||
static vm_map_entry_t | static void | ||||
vm_map_entry_splay(vm_offset_t addr, vm_map_entry_t root) | vm_map_splay(vm_offset_t addr, vm_map_t map, vm_map_entry_t *io) | ||||
{ | { | ||||
vm_map_entry_t llist, rlist; | vm_map_entry_t llist, rlist; | ||||
vm_map_entry_t ltree, rtree; | vm_map_entry_t ltree, rtree; | ||||
vm_map_entry_t y; | vm_map_entry_t root, x, y; | ||||
/* Special case of empty tree. */ | KASSERT(addr >= map->header.end && addr < map->header.start, | ||||
if (root == NULL) | ("vm_map_splay: addr %jx, offsets start %jx, end %jx", | ||||
return (root); | (uintmax_t)addr, | ||||
(uintmax_t)map->header.end, (uintmax_t)map->header.start)); | |||||
/* | /* | ||||
* Pass One: Splay down the tree until we find addr or a NULL | * Pass One: Splay down the tree until we find addr or a NULL | ||||
Context not available. | |||||
*/ | */ | ||||
llist = NULL; | llist = NULL; | ||||
rlist = NULL; | rlist = NULL; | ||||
for (;;) { | root = map->root; | ||||
/* root is never NULL in here. */ | do { | ||||
if (addr < root->start) { | x = root; | ||||
y = root->left; | /* x is never NULL in here. */ | ||||
if (y == NULL) | if (addr >= x->end) { | ||||
break; | y = x->right; | ||||
if (addr < y->start && y->left != NULL) { | if (y != NULL && addr >= y->end) { | ||||
/* Rotate right and put y on rlist. */ | root = y->right; | ||||
root->left = y->right; | /* Rotate left. */ | ||||
y->right = root; | x->right = y->left; | ||||
vm_map_entry_set_max_free(root); | y->left = x; | ||||
vm_map_entry_set_max_free(x); | |||||
/* Put y on llist. */ | |||||
y->right = llist; | |||||
llist = y; | |||||
} else if (y != NULL && addr < y->start) { | |||||
root = y->left; | root = y->left; | ||||
/* Put x on llist. */ | |||||
x->right = llist; | |||||
llist = x; | |||||
/* Put y on rlist. */ | |||||
y->left = rlist; | y->left = rlist; | ||||
rlist = y; | rlist = y; | ||||
} else { | } else { | ||||
/* Put root on rlist. */ | |||||
root->left = rlist; | |||||
rlist = root; | |||||
root = y; | root = y; | ||||
} | /* Put x on llist. */ | ||||
} else if (addr >= root->end) { | x->right = llist; | ||||
y = root->right; | llist = x; | ||||
if (y == NULL) | |||||
break; | break; | ||||
if (addr >= y->end && y->right != NULL) { | } | ||||
/* Rotate left and put y on llist. */ | } else if (addr < x->start) { | ||||
root->right = y->left; | y = x->left; | ||||
y->left = root; | if (y != NULL && addr >= y->end) { | ||||
vm_map_entry_set_max_free(root); | |||||
root = y->right; | root = y->right; | ||||
/* Put x on rlist. */ | |||||
x->left = rlist; | |||||
rlist = x; | |||||
/* Put y on llist. */ | |||||
y->right = llist; | y->right = llist; | ||||
llist = y; | llist = y; | ||||
} else if (y != NULL && addr < y->start) { | |||||
root = y->left; | |||||
/* Rotate right. */ | |||||
x->left = y->right; | |||||
y->right = x; | |||||
vm_map_entry_set_max_free(x); | |||||
/* Put y on rlist. */ | |||||
y->left = rlist; | |||||
rlist = y; | |||||
} else { | } else { | ||||
/* Put root on llist. */ | |||||
root->right = llist; | |||||
llist = root; | |||||
root = y; | root = y; | ||||
/* Put x on rlist. */ | |||||
x->left = rlist; | |||||
rlist = x; | |||||
break; | |||||
} | } | ||||
} else | } else | ||||
break; | break; | ||||
} while (root != NULL); | |||||
if (root == NULL && | |||||
(io == NULL || *io == NULL)) { | |||||
/* | |||||
* With no matching node found, and no new node to | |||||
* insert, recover the greatest node in the left | |||||
* subtree and make it the root. There is such a | |||||
* node, since map->header is in the tree and left of | |||||
* all addresses. | |||||
*/ | |||||
rtree = NULL; | |||||
root = llist; | |||||
llist = llist->right; | |||||
ltree = root->left; | |||||
} else if (root == NULL) { | |||||
/* Install the new item as tree root. */ | |||||
rtree = NULL; | |||||
root = *io; | |||||
*io = NULL; | |||||
llist->next = rlist->prev = root; | |||||
root->prev = llist; | |||||
root->next = rlist; | |||||
llist->adj_free = root->start - llist->end; | |||||
root->adj_free = rlist->start - root->end; | |||||
ltree = NULL; | |||||
} else if (io == NULL || *io != NULL) { | |||||
rtree = root->right; | |||||
ltree = root->left; | |||||
} else { | |||||
/* | |||||
* To delete the found item from the tree, walk the | |||||
* left spine of the found subtree, extending the left | |||||
* spine of the new subtree, so that the predecessor | |||||
* of the found node can be the new root. | |||||
*/ | |||||
rtree = root->right; | |||||
*io = root; | |||||
root = root->left; | |||||
if (root == NULL) { | |||||
root = llist; | |||||
llist = llist->right; | |||||
} else { | |||||
for(;;) { | |||||
y = root->right; | |||||
if (y == NULL) | |||||
break; | |||||
x = root; | |||||
root = y->right; | |||||
/* Rotate left. */ | |||||
x->right = y->left; | |||||
y->left = x; | |||||
vm_map_entry_set_max_free(x); | |||||
if (root == NULL) { | |||||
root = y; | |||||
break; | |||||
} | |||||
/* Put y on llist. */ | |||||
y->right = llist; | |||||
llist = y; | |||||
} | |||||
} | |||||
ltree = root->left; | |||||
root->next = (*io)->next; | |||||
root->next->prev = root; | |||||
root->adj_free = root->next->start - root->end; | |||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
* and set max_free. The subtrees of the root go at the | * and set max_free. The subtrees of the root go at the | ||||
* bottom of llist and rlist. | * bottom of llist and rlist. | ||||
*/ | */ | ||||
ltree = root->left; | |||||
while (llist != NULL) { | while (llist != NULL) { | ||||
y = llist->right; | y = llist->right; | ||||
llist->right = ltree; | llist->right = ltree; | ||||
Context not available. | |||||
ltree = llist; | ltree = llist; | ||||
llist = y; | llist = y; | ||||
} | } | ||||
rtree = root->right; | |||||
while (rlist != NULL) { | while (rlist != NULL) { | ||||
y = rlist->left; | y = rlist->left; | ||||
rlist->left = rtree; | rlist->left = rtree; | ||||
Context not available. | |||||
root->right = rtree; | root->right = rtree; | ||||
vm_map_entry_set_max_free(root); | vm_map_entry_set_max_free(root); | ||||
return (root); | map->root = root; | ||||
} | } | ||||
/* | /* | ||||
Context not available. | |||||
*/ | */ | ||||
static void | static void | ||||
vm_map_entry_link(vm_map_t map, | vm_map_entry_link(vm_map_t map, | ||||
vm_map_entry_t after_where, | |||||
vm_map_entry_t entry) | vm_map_entry_t entry) | ||||
{ | { | ||||
CTR4(KTR_VM, | CTR3(KTR_VM, | ||||
"vm_map_entry_link: map %p, nentries %d, entry %p, after %p", map, | "vm_map_entry_link: map %p, nentries %d, entry %p", map, | ||||
map->nentries, entry, after_where); | map->nentries, entry); | ||||
VM_MAP_ASSERT_LOCKED(map); | VM_MAP_ASSERT_LOCKED(map); | ||||
KASSERT(after_where->end <= entry->start, | |||||
("vm_map_entry_link: prev end %jx new start %jx overlap", | |||||
(uintmax_t)after_where->end, (uintmax_t)entry->start)); | |||||
KASSERT(entry->end <= after_where->next->start, | |||||
("vm_map_entry_link: new end %jx next start %jx overlap", | |||||
(uintmax_t)entry->end, (uintmax_t)after_where->next->start)); | |||||
map->nentries++; | map->nentries++; | ||||
entry->prev = after_where; | vm_map_splay(entry->start, map, &entry); | ||||
entry->next = after_where->next; | |||||
entry->next->prev = entry; | |||||
after_where->next = entry; | |||||
if (after_where != &map->header) { | |||||
if (after_where != map->root) | |||||
vm_map_entry_splay(after_where->start, map->root); | |||||
entry->right = after_where->right; | |||||
entry->left = after_where; | |||||
after_where->right = NULL; | |||||
after_where->adj_free = entry->start - after_where->end; | |||||
vm_map_entry_set_max_free(after_where); | |||||
} else { | |||||
entry->right = map->root; | |||||
entry->left = NULL; | |||||
} | |||||
entry->adj_free = entry->next->start - entry->end; | |||||
vm_map_entry_set_max_free(entry); | |||||
map->root = entry; | |||||
} | } | ||||
static void | static void | ||||
vm_map_entry_unlink(vm_map_t map, | vm_map_entry_unlink(vm_map_t map, | ||||
vm_map_entry_t entry) | vm_map_entry_t entry) | ||||
{ | { | ||||
vm_map_entry_t next, prev, root; | vm_map_entry_t dead; | ||||
VM_MAP_ASSERT_LOCKED(map); | VM_MAP_ASSERT_LOCKED(map); | ||||
if (entry != map->root) | dead = NULL; | ||||
vm_map_entry_splay(entry->start, map->root); | vm_map_splay(entry->start, map, &dead); | ||||
if (entry->left == NULL) | |||||
root = entry->right; | |||||
else { | |||||
root = vm_map_entry_splay(entry->start, entry->left); | |||||
root->right = entry->right; | |||||
root->adj_free = entry->next->start - root->end; | |||||
vm_map_entry_set_max_free(root); | |||||
} | |||||
map->root = root; | |||||
prev = entry->prev; | |||||
next = entry->next; | |||||
next->prev = prev; | |||||
prev->next = next; | |||||
map->nentries--; | map->nentries--; | ||||
CTR3(KTR_VM, "vm_map_entry_unlink: map %p, nentries %d, entry %p", map, | CTR3(KTR_VM, "vm_map_entry_unlink: map %p, nentries %d, entry %p", map, | ||||
map->nentries, entry); | map->nentries, entry); | ||||
Context not available. | |||||
* root and making the change there. | * root and making the change there. | ||||
*/ | */ | ||||
if (entry != map->root) | if (entry != map->root) | ||||
map->root = vm_map_entry_splay(entry->start, map->root); | vm_map_splay(entry->start, map, NULL); | ||||
entry->adj_free = entry->next->start - entry->end; | entry->adj_free = entry->next->start - entry->end; | ||||
vm_map_entry_set_max_free(entry); | vm_map_entry_set_max_free(entry); | ||||
Context not available. | |||||
vm_map_entry_t cur; | vm_map_entry_t cur; | ||||
boolean_t locked; | boolean_t locked; | ||||
/* | |||||
* If the address is out of range, fail immediately. | |||||
*/ | |||||
if (address < map->header.end || address >= map->header.start) { | |||||
*entry = &map->header; | |||||
return (FALSE); | |||||
} | |||||
/* | /* | ||||
* If the map is empty, then the map entry immediately preceding | * If the map is empty, then the map entry immediately preceding | ||||
* "address" is the map's header. | * "address" is the map's header. | ||||
*/ | */ | ||||
cur = map->root; | cur = map->root; | ||||
if (cur == NULL) | if (address >= cur->start && cur->end > address) { | ||||
*entry = &map->header; | |||||
else if (address >= cur->start && cur->end > address) { | |||||
*entry = cur; | *entry = cur; | ||||
return (TRUE); | return (TRUE); | ||||
} else if ((locked = vm_map_locked(map)) || | } | ||||
sx_try_upgrade(&map->lock)) { | if ((locked = vm_map_locked(map)) || sx_try_upgrade(&map->lock)) { | ||||
/* | /* | ||||
* Splay requires a write lock on the map. However, it only | * Splay requires a write lock on the map. However, it only | ||||
* restructures the binary search tree; it does not otherwise | * restructures the binary search tree; it does not otherwise | ||||
* change the map. Thus, the map's timestamp need not change | * change the map. Thus, the map's timestamp need not change | ||||
* on a temporary upgrade. | * on a temporary upgrade. | ||||
*/ | */ | ||||
map->root = cur = vm_map_entry_splay(address, cur); | vm_map_splay(address, map, NULL); | ||||
cur = map->root; | |||||
if (!locked) | if (!locked) | ||||
sx_downgrade(&map->lock); | sx_downgrade(&map->lock); | ||||
/* | *entry = cur; | ||||
* If "address" is contained within a map entry, the new root | if (cur->end > address) | ||||
* is that map entry. Otherwise, the new root is a map entry | return (TRUE); | ||||
* immediately before or after "address". | |||||
*/ | |||||
if (address >= cur->start) { | |||||
*entry = cur; | |||||
if (cur->end > address) | |||||
return (TRUE); | |||||
} else | |||||
*entry = cur->prev; | |||||
} else | } else | ||||
/* | /* | ||||
* Since the map is only locked for read access, perform a | * Since the map is only locked for read access, perform a | ||||
* standard binary search tree lookup for "address". | * standard binary search tree lookup for "address". | ||||
*/ | */ | ||||
for (;;) { | do { | ||||
if (address < cur->start) { | if (cur->end <= address) { | ||||
if (cur->left == NULL) { | *entry = cur; | ||||
*entry = cur->prev; | cur = cur->right; | ||||
break; | } else if (address < cur->start) { | ||||
} | |||||
cur = cur->left; | cur = cur->left; | ||||
} else if (cur->end > address) { | } else { | ||||
*entry = cur; | *entry = cur; | ||||
return (TRUE); | return (TRUE); | ||||
} else { | |||||
if (cur->right == NULL) { | |||||
*entry = cur; | |||||
break; | |||||
} | |||||
cur = cur->right; | |||||
} | } | ||||
} | } while (cur != NULL); | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
Context not available. | |||||
/* | /* | ||||
* Insert the new entry into the list | * Insert the new entry into the list | ||||
*/ | */ | ||||
vm_map_entry_link(map, prev_entry, new_entry); | vm_map_entry_link(map, new_entry); | ||||
if ((new_entry->eflags & MAP_ENTRY_GUARD) == 0) | if ((new_entry->eflags & MAP_ENTRY_GUARD) == 0) | ||||
map->size += new_entry->end - new_entry->start; | map->size += new_entry->end - new_entry->start; | ||||
Context not available. | |||||
vm_offset_t *addr) /* OUT */ | vm_offset_t *addr) /* OUT */ | ||||
{ | { | ||||
vm_map_entry_t entry; | vm_map_entry_t entry; | ||||
vm_offset_t st; | |||||
/* | /* | ||||
* Request must fit within min/max VM address and must avoid | * Request must fit within min/max VM address and must avoid | ||||
Context not available. | |||||
if (start + length > vm_map_max(map) || start + length < start) | if (start + length > vm_map_max(map) || start + length < start) | ||||
return (1); | return (1); | ||||
/* Empty tree means wide open address space. */ | |||||
if (map->root == NULL) { | |||||
*addr = start; | |||||
return (0); | |||||
} | |||||
/* | |||||
* After splay, if start comes before root node, then there | |||||
* must be a gap from start to the root. | |||||
*/ | |||||
map->root = vm_map_entry_splay(start, map->root); | |||||
if (start + length <= map->root->start) { | |||||
*addr = start; | |||||
return (0); | |||||
} | |||||
/* | /* | ||||
* Root is the last node that might begin its gap before | * Root is the last node that might begin its gap before | ||||
* start, and this is the last comparison where address | * start, and this is the last comparison where address | ||||
* wrap might be a problem. | * wrap might be a problem. | ||||
*/ | */ | ||||
st = (start > map->root->end) ? start : map->root->end; | vm_map_splay(start, map, NULL); | ||||
if (length <= map->root->end + map->root->adj_free - st) { | entry = map->root; | ||||
*addr = st; | start = MAX(start, entry->end); | ||||
if (length <= entry->end + entry->adj_free - start) { | |||||
*addr = start; | |||||
return (0); | return (0); | ||||
} | } | ||||
/* With max_free, can immediately tell if no solution. */ | /* With max_free, can immediately tell if no solution. */ | ||||
entry = map->root->right; | entry = entry->right; | ||||
if (entry == NULL || length > entry->max_free) | if (entry == NULL || length > entry->max_free) | ||||
return (1); | return (1); | ||||
Context not available. | |||||
* right subtree (first fit). The previous splay implies that | * right subtree (first fit). The previous splay implies that | ||||
* all regions in the right subtree have addresses > start. | * all regions in the right subtree have addresses > start. | ||||
*/ | */ | ||||
while (entry != NULL) { | for (;;) { | ||||
if (entry->left != NULL && entry->left->max_free >= length) | if (entry->left != NULL && entry->left->max_free >= length) | ||||
entry = entry->left; | entry = entry->left; | ||||
else if (entry->adj_free >= length) { | else if (entry->adj_free >= length) { | ||||
*addr = entry->end; | *addr = entry->end; | ||||
return (0); | return (0); | ||||
} else | } else if (entry->right != NULL) | ||||
entry = entry->right; | entry = entry->right; | ||||
else { | |||||
/* Can't get here, so panic if we do. */ | |||||
panic("vm_map_findspace: max_free corrupt"); | |||||
} | |||||
} | } | ||||
/* Can't get here, so panic if we do. */ | |||||
panic("vm_map_findspace: max_free corrupt"); | |||||
} | } | ||||
int | int | ||||
Context not available. | |||||
} | } | ||||
} | } | ||||
static boolean_t | |||||
kib: Change the return type to bool ? | |||||
vm_map_mergeable_neighbors(vm_map_entry_t prev, vm_map_entry_t entry) | |||||
{ | |||||
vm_size_t prevsize; | |||||
prevsize = prev->end - prev->start; | |||||
return ( (prev->end == entry->start) && | |||||
Done Inline ActionsAlmost all () there and below are excessive, and no need in space before the excessive '(' at this line. kib: Almost all () there and below are excessive, and no need in space before the excessive '(' at… | |||||
(prev->object.vm_object == entry->object.vm_object) && | |||||
(!prev->object.vm_object || | |||||
(prev->offset + prevsize == entry->offset)) && | |||||
Done Inline ActionsNo need in additional space for indent. kib: No need in additional space for indent. | |||||
(prev->eflags == entry->eflags) && | |||||
(prev->protection == entry->protection) && | |||||
(prev->max_protection == entry->max_protection) && | |||||
(prev->inheritance == entry->inheritance) && | |||||
(prev->wired_count == entry->wired_count) && | |||||
(prev->cred == entry->cred)); | |||||
} | |||||
static void | |||||
vm_map_merged_neighbor_dispose(vm_map_t map, vm_map_entry_t entry) | |||||
{ | |||||
vm_map_entry_unlink(map, entry); | |||||
/* | |||||
Done Inline ActionsBlank line is needed before start of multi-line comment. kib: Blank line is needed before start of multi-line comment. | |||||
* If the backing object is a vnode object, | |||||
* vm_object_deallocate() calls vrele(). | |||||
* However, vrele() does not lock the vnode | |||||
* because the vnode has additional | |||||
* references. Thus, the map lock can be kept | |||||
* without causing a lock-order reversal with | |||||
* the vnode lock. | |||||
* | |||||
* Since we count the number of virtual page | |||||
* mappings in object->un_pager.vnp.writemappings, | |||||
* the writemappings value should not be adjusted | |||||
* when the entry is disposed of. | |||||
*/ | |||||
if (entry->object.vm_object) | |||||
Done Inline Actions!= NULL kib: != NULL | |||||
vm_object_deallocate(entry->object.vm_object); | |||||
if (entry->cred != NULL) | |||||
crfree(entry->cred); | |||||
vm_map_entry_dispose(map, entry); | |||||
} | |||||
/* | /* | ||||
* vm_map_simplify_entry: | * vm_map_simplify_entry: | ||||
* | * | ||||
Context not available. | |||||
vm_map_simplify_entry(vm_map_t map, vm_map_entry_t entry) | vm_map_simplify_entry(vm_map_t map, vm_map_entry_t entry) | ||||
{ | { | ||||
vm_map_entry_t next, prev; | vm_map_entry_t next, prev; | ||||
vm_size_t prevsize, esize; | |||||
if ((entry->eflags & (MAP_ENTRY_GROWS_DOWN | MAP_ENTRY_GROWS_UP | | if ((entry->eflags & (MAP_ENTRY_GROWS_DOWN | MAP_ENTRY_GROWS_UP | | ||||
MAP_ENTRY_IN_TRANSITION | MAP_ENTRY_IS_SUB_MAP)) != 0) | MAP_ENTRY_IN_TRANSITION | MAP_ENTRY_IS_SUB_MAP)) != 0) | ||||
Context not available. | |||||
prev = entry->prev; | prev = entry->prev; | ||||
if (prev != &map->header) { | if (prev != &map->header) { | ||||
prevsize = prev->end - prev->start; | if (vm_map_mergeable_neighbors(prev, entry)) { | ||||
if ( (prev->end == entry->start) && | |||||
(prev->object.vm_object == entry->object.vm_object) && | |||||
(!prev->object.vm_object || | |||||
(prev->offset + prevsize == entry->offset)) && | |||||
(prev->eflags == entry->eflags) && | |||||
(prev->protection == entry->protection) && | |||||
(prev->max_protection == entry->max_protection) && | |||||
(prev->inheritance == entry->inheritance) && | |||||
(prev->wired_count == entry->wired_count) && | |||||
(prev->cred == entry->cred)) { | |||||
vm_map_entry_unlink(map, prev); | |||||
entry->start = prev->start; | entry->start = prev->start; | ||||
entry->offset = prev->offset; | entry->offset = prev->offset; | ||||
if (entry->prev != &map->header) | vm_map_merged_neighbor_dispose(map, prev); | ||||
vm_map_entry_resize_free(map, entry->prev); | |||||
/* | |||||
* If the backing object is a vnode object, | |||||
* vm_object_deallocate() calls vrele(). | |||||
* However, vrele() does not lock the vnode | |||||
* because the vnode has additional | |||||
* references. Thus, the map lock can be kept | |||||
* without causing a lock-order reversal with | |||||
* the vnode lock. | |||||
* | |||||
* Since we count the number of virtual page | |||||
* mappings in object->un_pager.vnp.writemappings, | |||||
* the writemappings value should not be adjusted | |||||
* when the entry is disposed of. | |||||
*/ | |||||
if (prev->object.vm_object) | |||||
vm_object_deallocate(prev->object.vm_object); | |||||
if (prev->cred != NULL) | |||||
crfree(prev->cred); | |||||
vm_map_entry_dispose(map, prev); | |||||
} | } | ||||
} | } | ||||
next = entry->next; | next = entry->next; | ||||
if (next != &map->header) { | if (next != &map->header) { | ||||
esize = entry->end - entry->start; | if (vm_map_mergeable_neighbors(entry, next)) { | ||||
if ((entry->end == next->start) && | |||||
(next->object.vm_object == entry->object.vm_object) && | |||||
(!entry->object.vm_object || | |||||
(entry->offset + esize == next->offset)) && | |||||
(next->eflags == entry->eflags) && | |||||
(next->protection == entry->protection) && | |||||
(next->max_protection == entry->max_protection) && | |||||
(next->inheritance == entry->inheritance) && | |||||
(next->wired_count == entry->wired_count) && | |||||
(next->cred == entry->cred)) { | |||||
vm_map_entry_unlink(map, next); | |||||
entry->end = next->end; | entry->end = next->end; | ||||
vm_map_entry_resize_free(map, entry); | vm_map_merged_neighbor_dispose(map, next); | ||||
/* | |||||
* See comment above. | |||||
*/ | |||||
if (next->object.vm_object) | |||||
vm_object_deallocate(next->object.vm_object); | |||||
if (next->cred != NULL) | |||||
crfree(next->cred); | |||||
vm_map_entry_dispose(map, next); | |||||
} | } | ||||
} | } | ||||
} | } | ||||
Context not available. | |||||
if (new_entry->cred != NULL) | if (new_entry->cred != NULL) | ||||
crhold(entry->cred); | crhold(entry->cred); | ||||
vm_map_entry_link(map, entry->prev, new_entry); | vm_map_entry_link(map, new_entry); | ||||
if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { | if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { | ||||
vm_object_reference(new_entry->object.vm_object); | vm_object_reference(new_entry->object.vm_object); | ||||
Context not available. | |||||
if (new_entry->cred != NULL) | if (new_entry->cred != NULL) | ||||
crhold(entry->cred); | crhold(entry->cred); | ||||
vm_map_entry_link(map, entry, new_entry); | vm_map_entry_link(map, new_entry); | ||||
if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { | if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { | ||||
vm_object_reference(new_entry->object.vm_object); | vm_object_reference(new_entry->object.vm_object); | ||||
Context not available. | |||||
* Insert the entry into the new map -- we know we're | * Insert the entry into the new map -- we know we're | ||||
* inserting at the end of the new map. | * inserting at the end of the new map. | ||||
*/ | */ | ||||
vm_map_entry_link(new_map, new_map->header.prev, | vm_map_entry_link(new_map, new_entry); | ||||
new_entry); | |||||
vmspace_map_entry_forked(vm1, vm2, new_entry); | vmspace_map_entry_forked(vm1, vm2, new_entry); | ||||
/* | /* | ||||
Context not available. | |||||
new_entry->wired_count = 0; | new_entry->wired_count = 0; | ||||
new_entry->object.vm_object = NULL; | new_entry->object.vm_object = NULL; | ||||
new_entry->cred = NULL; | new_entry->cred = NULL; | ||||
vm_map_entry_link(new_map, new_map->header.prev, | vm_map_entry_link(new_map, new_entry); | ||||
new_entry); | |||||
vmspace_map_entry_forked(vm1, vm2, new_entry); | vmspace_map_entry_forked(vm1, vm2, new_entry); | ||||
vm_map_copy_entry(old_map, new_map, old_entry, | vm_map_copy_entry(old_map, new_map, old_entry, | ||||
new_entry, fork_charge); | new_entry, fork_charge); | ||||
Context not available. | |||||
new_entry->max_protection = old_entry->max_protection; | new_entry->max_protection = old_entry->max_protection; | ||||
new_entry->inheritance = VM_INHERIT_ZERO; | new_entry->inheritance = VM_INHERIT_ZERO; | ||||
vm_map_entry_link(new_map, new_map->header.prev, | vm_map_entry_link(new_map, new_entry); | ||||
new_entry); | |||||
vmspace_map_entry_forked(vm1, vm2, new_entry); | vmspace_map_entry_forked(vm1, vm2, new_entry); | ||||
new_entry->cred = curthread->td_ucred; | new_entry->cred = curthread->td_ucred; | ||||
Context not available. | |||||
static void | static void | ||||
vm_map_print(vm_map_t map) | vm_map_print(vm_map_t map) | ||||
{ | { | ||||
vm_map_entry_t entry; | vm_map_entry_t entry, prev; | ||||
db_iprintf("Task map %p: pmap=%p, nentries=%d, version=%u\n", | db_iprintf("Task map %p: pmap=%p, nentries=%d, version=%u\n", | ||||
(void *)map, | (void *)map, | ||||
(void *)map->pmap, map->nentries, map->timestamp); | (void *)map->pmap, map->nentries, map->timestamp); | ||||
db_indent += 2; | db_indent += 2; | ||||
for (entry = map->header.next; entry != &map->header; | for (prev = &map->header; (entry = prev->next) != &map->header; | ||||
entry = entry->next) { | prev = entry) { | ||||
db_iprintf("map entry %p: start=%p, end=%p, eflags=%#x, \n", | db_iprintf("map entry %p: start=%p, end=%p, eflags=%#x, \n", | ||||
(void *)entry, (void *)entry->start, (void *)entry->end, | (void *)entry, (void *)entry->start, (void *)entry->end, | ||||
entry->eflags); | entry->eflags); | ||||
Context not available. | |||||
db_printf(", share=%p, offset=0x%jx\n", | db_printf(", share=%p, offset=0x%jx\n", | ||||
(void *)entry->object.sub_map, | (void *)entry->object.sub_map, | ||||
(uintmax_t)entry->offset); | (uintmax_t)entry->offset); | ||||
if ((entry->prev == &map->header) || | if ((prev == &map->header) || | ||||
(entry->prev->object.sub_map != | (prev->object.sub_map != | ||||
entry->object.sub_map)) { | entry->object.sub_map)) { | ||||
db_indent += 2; | db_indent += 2; | ||||
vm_map_print((vm_map_t)entry->object.sub_map); | vm_map_print((vm_map_t)entry->object.sub_map); | ||||
Context not available. | |||||
(entry->eflags & MAP_ENTRY_NEEDS_COPY) ? "needed" : "done"); | (entry->eflags & MAP_ENTRY_NEEDS_COPY) ? "needed" : "done"); | ||||
db_printf("\n"); | db_printf("\n"); | ||||
if ((entry->prev == &map->header) || | if ((prev == &map->header) || | ||||
(entry->prev->object.vm_object != | (prev->object.vm_object != | ||||
entry->object.vm_object)) { | entry->object.vm_object)) { | ||||
db_indent += 2; | db_indent += 2; | ||||
vm_object_print((db_expr_t)(intptr_t) | vm_object_print((db_expr_t)(intptr_t) | ||||
Context not available. |
Change the return type to bool ?