aboutsummaryrefslogtreecommitdiff
path: root/vm/vm_object.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm/vm_object.c')
-rw-r--r--vm/vm_object.c53
1 files changed, 40 insertions, 13 deletions
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;
}