summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vm/vm_map.c11
-rw-r--r--vm/vm_object.c53
-rw-r--r--vm/vm_object.h4
3 files changed, 49 insertions, 19 deletions
diff --git a/vm/vm_map.c b/vm/vm_map.c
index 62fb87b9..55a822af 100644
--- a/vm/vm_map.c
+++ b/vm/vm_map.c
@@ -1064,7 +1064,9 @@ kern_return_t vm_map_enter(
entry->offset,
offset,
(vm_size_t)(entry->vme_end - entry->vme_start),
- size)) {
+ size,
+ &entry->object.vm_object,
+ &entry->offset)) {
/*
* Coalesced the two objects - can extend
@@ -1074,7 +1076,6 @@ kern_return_t vm_map_enter(
map->size += size;
entry->vme_end = end;
vm_map_gap_update(&map->hdr, entry);
- vm_object_deallocate(object);
RETURN(KERN_SUCCESS);
}
}
@@ -1092,7 +1093,9 @@ kern_return_t vm_map_enter(
offset,
next_entry->offset,
size,
- (vm_size_t)(next_entry->vme_end - next_entry->vme_start))) {
+ (vm_size_t)(next_entry->vme_end - next_entry->vme_start),
+ &next_entry->object.vm_object,
+ &next_entry->offset)) {
/*
* Coalesced the two objects - can extend
@@ -1101,9 +1104,7 @@ kern_return_t vm_map_enter(
*/
map->size += size;
next_entry->vme_start = start;
- next_entry->offset -= size;
vm_map_gap_update(&map->hdr, entry);
- vm_object_deallocate(object);
RETURN(KERN_SUCCESS);
}
}
diff --git a/vm/vm_object.c b/vm/vm_object.c
index e01c1856..c238cce4 100644
--- a/vm/vm_object.c
+++ b/vm/vm_object.c
@@ -2687,15 +2687,16 @@ void vm_object_page_remove(
/*
* Routine: vm_object_coalesce
- * Function: Coalesces two objects backing up adjoining
- * regions of memory into a single object.
- *
- * returns TRUE if objects were combined.
- *
- * NOTE: Only works at the moment if one of the objects is NULL
- * or if the objects are the same - otherwise, which
- * object do we lock first?
- *
+ * Purpose:
+ * Tries to coalesce two objects backing up adjoining
+ * regions of memory into a single object.
+ *
+ * NOTE: Only works at the moment if one of the objects
+ * is NULL or if the objects are the same - otherwise,
+ * which object do we lock first?
+ * Returns:
+ * TRUE if objects have been coalesced.
+ * FALSE the objects could not be coalesced.
* Parameters:
* prev_object First object to coalesce
* prev_offset Offset into prev_object
@@ -2705,8 +2706,14 @@ void vm_object_page_remove(
* prev_size Size of reference to prev_object
* next_size Size of reference to next_object
*
+ * new_object Resulting colesced object
+ * new_offset Offset into the resulting object
* Conditions:
- * The object must *not* be locked.
+ * The objects must *not* be locked.
+ *
+ * If the objects are coalesced successfully, the caller's
+ * references for both objects are consumed, and the caller
+ * gains a reference for the new object.
*/
boolean_t vm_object_coalesce(
@@ -2715,7 +2722,9 @@ boolean_t vm_object_coalesce(
vm_offset_t prev_offset,
vm_offset_t next_offset,
vm_size_t prev_size,
- vm_size_t next_size)
+ vm_size_t next_size,
+ vm_object_t *new_object, /* OUT */
+ vm_offset_t *new_offset) /* OUT */
{
vm_object_t object;
vm_size_t newsize;
@@ -2725,10 +2734,23 @@ boolean_t vm_object_coalesce(
* If neither object actually exists,
* the offsets don't matter.
*/
- if (prev_object == VM_OBJECT_NULL)
+ if (prev_object == VM_OBJECT_NULL) {
+ *new_object = VM_OBJECT_NULL;
+ *new_offset = 0;
return TRUE;
+ }
- return prev_offset + prev_size == next_offset;
+ if (prev_offset + prev_size == next_offset) {
+ *new_object = prev_object;
+ *new_offset = prev_offset;
+ /*
+ * Deallocate one of the two references.
+ */
+ vm_object_deallocate(prev_object);
+ return TRUE;
+ }
+
+ return FALSE;
}
if (next_object != VM_OBJECT_NULL) {
@@ -2785,6 +2807,8 @@ boolean_t vm_object_coalesce(
newsize = prev_offset + prev_size + next_size;
if (newsize > object->size)
object->size = newsize;
+
+ *new_offset = prev_offset;
} else {
/*
* Check if we have enough space in the object
@@ -2802,9 +2826,12 @@ boolean_t vm_object_coalesce(
vm_object_page_remove(object,
next_offset - prev_size,
next_offset);
+
+ *new_offset = next_offset - prev_size;
}
vm_object_unlock(object);
+ *new_object = object;
return TRUE;
}
diff --git a/vm/vm_object.h b/vm/vm_object.h
index 46328a38..9c17541f 100644
--- a/vm/vm_object.h
+++ b/vm/vm_object.h
@@ -247,7 +247,9 @@ extern boolean_t vm_object_coalesce(
vm_offset_t prev_offset,
vm_offset_t next_offset,
vm_size_t prev_size,
- vm_size_t next_size);
+ vm_size_t next_size,
+ vm_object_t *new_object, /* OUT */
+ vm_offset_t *new_offset); /* OUT */
extern void vm_object_pager_wakeup(ipc_port_t pager);