[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v2 2/3] vm: Add vm_map_coalesce_entry
From: |
Sergey Bugaev |
Subject: |
[PATCH v2 2/3] vm: Add vm_map_coalesce_entry |
Date: |
Wed, 5 Jul 2023 17:16:38 +0300 |
This function attempts to coalesce a VM map entry with its preceeding
entry. It wraps vm_object_coalesce.
---
vm/vm_map.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++--
vm/vm_map.h | 2 ++
2 files changed, 78 insertions(+), 2 deletions(-)
diff --git a/vm/vm_map.c b/vm/vm_map.c
index d147d4b2..4ddde212 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
@@ -4930,6 +4929,81 @@ vm_region_create_proxy (task_t task, vm_address_t
address,
return ret;
}
+/*
+ * 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:
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,
--
2.41.0