summaryrefslogtreecommitdiff
path: root/vm
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2023-07-05 17:16:38 +0300
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2023-11-27 01:11:10 +0100
commit87e8ddc7adac201aebe932b2d6f45b36c79849dd (patch)
tree7888de3ea215c991afbff22956ab4d409d068448 /vm
parent1754dce141db6f79dbdc4f616f9d85204758b3fb (diff)
vm: Add vm_map_coalesce_entry
This function attempts to coalesce a VM map entry with its preceeding entry. It wraps vm_object_coalesce. Message-ID: <20230705141639.85792-3-bugaevc@gmail.com>
Diffstat (limited to 'vm')
-rw-r--r--vm/vm_map.c78
-rw-r--r--vm/vm_map.h2
2 files changed, 78 insertions, 2 deletions
diff --git a/vm/vm_map.c b/vm/vm_map.c
index 62ab8184..d4280de3 100644
--- a/vm/vm_map.c
+++ b/vm/vm_map.c
@@ -113,8 +113,7 @@ MACRO_END
* start or end value.] Note that these clippings may not
* always be necessary (as the two resulting entries are then
* not changed); however, the clipping is done for convenience.
- * No attempt is currently made to "glue back together" two
- * abutting entries.
+ * The entries can later be "glued back together" (coalesced).
*
* The symmetric (shadow) copy strategy implements virtual copy
* by copying VM object references from one map to
@@ -4909,6 +4908,81 @@ vm_region_create_proxy (task_t task, vm_address_t address,
}
/*
+ * Routine: vm_map_coalesce_entry
+ * Purpose:
+ * Try to coalesce an entry with the preceeding entry in the map.
+ * Conditions:
+ * The map is locked. If coalesced, the entry is destroyed
+ * by the call.
+ * Returns:
+ * Whether the entry was coalesced.
+ */
+boolean_t
+vm_map_coalesce_entry(
+ vm_map_t map,
+ vm_map_entry_t entry)
+{
+ vm_map_entry_t prev = entry->vme_prev;
+ vm_size_t prev_size;
+ vm_size_t entry_size;
+
+ /*
+ * Check the basic conditions for coalescing the two entries.
+ */
+ if ((entry == vm_map_to_entry(map)) ||
+ (prev == vm_map_to_entry(map)) ||
+ (prev->vme_end != entry->vme_start) ||
+ (prev->is_shared || entry->is_shared) ||
+ (prev->is_sub_map || entry->is_sub_map) ||
+ (prev->inheritance != entry->inheritance) ||
+ (prev->protection != entry->protection) ||
+ (prev->max_protection != entry->max_protection) ||
+ (prev->needs_copy != entry->needs_copy) ||
+ (prev->in_transition || entry->in_transition) ||
+ (prev->wired_count != entry->wired_count) ||
+ (prev->projected_on != 0) ||
+ (entry->projected_on != 0))
+ return FALSE;
+
+ prev_size = prev->vme_end - prev->vme_start;
+ entry_size = entry->vme_end - entry->vme_start;
+ assert(prev->gap_size == 0);
+
+ /*
+ * See if we can coalesce the two objects.
+ */
+ if (!vm_object_coalesce(prev->object.vm_object,
+ entry->object.vm_object,
+ prev->offset,
+ entry->offset,
+ prev_size,
+ entry_size,
+ &prev->object.vm_object,
+ &prev->offset))
+ return FALSE;
+
+ /*
+ * Update the hints.
+ */
+ if (map->hint == entry)
+ SAVE_HINT(map, prev);
+ if (map->first_free == entry)
+ map->first_free = prev;
+
+ /*
+ * Get rid of the entry without changing any wirings or the pmap,
+ * and without altering map->size.
+ */
+ prev->vme_end = entry->vme_end;
+ vm_map_entry_unlink(map, entry);
+ vm_map_entry_dispose(map, entry);
+
+ return TRUE;
+}
+
+
+
+/*
* Routine: vm_map_machine_attribute
* Purpose:
* Provide machine-specific attributes to mappings,
diff --git a/vm/vm_map.h b/vm/vm_map.h
index 3d1c9428..a4949e4e 100644
--- a/vm/vm_map.h
+++ b/vm/vm_map.h
@@ -442,6 +442,8 @@ extern vm_map_copy_t vm_map_copy_copy(vm_map_copy_t);
extern kern_return_t vm_map_copy_discard_cont(vm_map_copyin_args_t,
vm_map_copy_t *);
+extern boolean_t vm_map_coalesce_entry(vm_map_t, vm_map_entry_t);
+
/* Add or remove machine- dependent attributes from map regions */
extern kern_return_t vm_map_machine_attribute(vm_map_t, vm_offset_t,
vm_size_t,