vm_map_simplify_entry considers merging an entry with its two

neighbors, and is used in a way so that if entries a and b cannot be
merged, we consider them twice, first not-merging a with its successor
b, and then not-merging b with its predecessor a. This change replaces
vm_map_simplify_entry with vm_map_try_merge_entries, which compares
two adjacent entries only, and uses it to avoid duplicated
merge-checks.

Tested by: pho
Reviewed by: alc
Approved by: markj (implicit)
Differential Revision: https://reviews.freebsd.org/D20814
This commit is contained in:
Doug Moore 2019-08-25 07:06:51 +00:00
parent 33d46a3cef
commit 83ea714f4f
3 changed files with 27 additions and 29 deletions

View File

@ -363,7 +363,7 @@ mac_proc_vm_revoke_recurse(struct thread *td, struct ucred *cred,
}
pmap_protect(map->pmap, vme->start, vme->end,
vme->protection & ~revokeperms);
vm_map_simplify_entry(map, vme);
vm_map_try_merge_entries(map, vme->prev, vme);
}
}
vm_map_unlock(map);

View File

@ -1554,7 +1554,7 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
map->size += end - prev_entry->end;
vm_map_entry_resize(map, prev_entry,
end - prev_entry->end);
vm_map_simplify_entry(map, prev_entry);
vm_map_try_merge_entries(map, prev_entry, prev_entry->next);
return (KERN_SUCCESS);
}
@ -1614,7 +1614,8 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_ooffset_t offset,
* with the previous entry when object is NULL. Here, we handle the
* other cases, which are less common.
*/
vm_map_simplify_entry(map, new_entry);
vm_map_try_merge_entries(map, prev_entry, new_entry);
vm_map_try_merge_entries(map, new_entry, new_entry->next);
if ((cow & (MAP_PREFAULT | MAP_PREFAULT_PARTIAL)) != 0) {
vm_map_pmap_enter(map, start, prot, object, OFF_TO_IDX(offset),
@ -2083,34 +2084,24 @@ vm_map_merged_neighbor_dispose(vm_map_t map, vm_map_entry_t entry)
}
/*
* vm_map_simplify_entry:
* vm_map_try_merge_entries:
*
* Simplify the given map entry by merging with either neighbor. This
* routine also has the ability to merge with both neighbors.
* Compare the given map entry to its predecessor, and merge its precessor
* into it if possible. The entry remains valid, and may be extended.
* The predecessor may be deleted.
*
* The map must be locked.
*
* This routine guarantees that the passed entry remains valid (though
* possibly extended). When merging, this routine may delete one or
* both neighbors.
*/
void
vm_map_simplify_entry(vm_map_t map, vm_map_entry_t entry)
vm_map_try_merge_entries(vm_map_t map, vm_map_entry_t prev, vm_map_entry_t entry)
{
vm_map_entry_t next, prev;
if ((entry->eflags & MAP_ENTRY_NOMERGE_MASK) != 0)
return;
prev = entry->prev;
if (vm_map_mergeable_neighbors(prev, entry)) {
VM_MAP_ASSERT_LOCKED(map);
if ((entry->eflags & MAP_ENTRY_NOMERGE_MASK) == 0 &&
vm_map_mergeable_neighbors(prev, entry)) {
vm_map_entry_unlink(map, prev, UNLINK_MERGE_NEXT);
vm_map_merged_neighbor_dispose(map, prev);
}
next = entry->next;
if (vm_map_mergeable_neighbors(entry, next)) {
vm_map_entry_unlink(map, next, UNLINK_MERGE_PREV);
vm_map_merged_neighbor_dispose(map, next);
}
}
/*
@ -2580,7 +2571,8 @@ vm_map_protect(vm_map_t map, vm_offset_t start, vm_offset_t end,
* [Note that clipping is not necessary the second time.]
*/
for (current = entry; current->start < end;
vm_map_simplify_entry(map, current), current = current->next) {
vm_map_try_merge_entries(map, current->prev, current),
current = current->next) {
if (rv != KERN_SUCCESS ||
(current->eflags & MAP_ENTRY_GUARD) != 0)
continue;
@ -2618,6 +2610,7 @@ vm_map_protect(vm_map_t map, vm_offset_t start, vm_offset_t end,
#undef MASK
}
}
vm_map_try_merge_entries(map, current->prev, current);
vm_map_unlock(map);
return (rv);
}
@ -2722,8 +2715,9 @@ vm_map_madvise(
default:
break;
}
vm_map_simplify_entry(map, current);
vm_map_try_merge_entries(map, current->prev, current);
}
vm_map_try_merge_entries(map, current->prev, current);
vm_map_unlock(map);
} else {
vm_pindex_t pstart, pend;
@ -2837,9 +2831,10 @@ vm_map_inherit(vm_map_t map, vm_offset_t start, vm_offset_t end,
if ((entry->eflags & MAP_ENTRY_GUARD) == 0 ||
new_inheritance != VM_INHERIT_ZERO)
entry->inheritance = new_inheritance;
vm_map_simplify_entry(map, entry);
vm_map_try_merge_entries(map, entry->prev, entry);
entry = entry->next;
}
vm_map_try_merge_entries(map, entry->prev, entry);
vm_map_unlock(map);
return (KERN_SUCCESS);
}
@ -3016,8 +3011,9 @@ vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end,
entry->eflags &= ~MAP_ENTRY_NEEDS_WAKEUP;
need_wakeup = true;
}
vm_map_simplify_entry(map, entry);
vm_map_try_merge_entries(map, entry->prev, entry);
}
vm_map_try_merge_entries(map, entry->prev, entry);
vm_map_unlock(map);
if (need_wakeup)
vm_map_wakeup(map);
@ -3313,8 +3309,9 @@ vm_map_wire_locked(vm_map_t map, vm_offset_t start, vm_offset_t end, int flags)
entry->eflags &= ~MAP_ENTRY_NEEDS_WAKEUP;
need_wakeup = true;
}
vm_map_simplify_entry(map, entry);
vm_map_try_merge_entries(map, entry->prev, entry);
}
vm_map_try_merge_entries(map, entry->prev, entry);
if (need_wakeup)
vm_map_wakeup(map);
return (rv);
@ -3952,8 +3949,8 @@ vmspace_fork(struct vmspace *vm1, vm_ooffset_t *fork_charge)
old_entry->object.vm_object);
/*
* As in vm_map_simplify_entry(), the
* vnode lock will not be acquired in
* As in vm_map_merged_neighbor_dispose(),
* the vnode lock will not be acquired in
* this call to vm_object_deallocate().
*/
vm_object_deallocate(object);

View File

@ -418,7 +418,8 @@ void vm_map_lookup_done (vm_map_t, vm_map_entry_t);
boolean_t vm_map_lookup_entry (vm_map_t, vm_offset_t, vm_map_entry_t *);
int vm_map_protect (vm_map_t, vm_offset_t, vm_offset_t, vm_prot_t, boolean_t);
int vm_map_remove (vm_map_t, vm_offset_t, vm_offset_t);
void vm_map_simplify_entry(vm_map_t map, vm_map_entry_t entry);
void vm_map_try_merge_entries(vm_map_t map, vm_map_entry_t prev,
vm_map_entry_t entry);
void vm_map_startup (void);
int vm_map_submap (vm_map_t, vm_offset_t, vm_offset_t, vm_map_t);
int vm_map_sync(vm_map_t, vm_offset_t, vm_offset_t, boolean_t, boolean_t);