summaryrefslogtreecommitdiff
path: root/vm/vm_object.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm/vm_object.c')
-rw-r--r--vm/vm_object.c145
1 files changed, 104 insertions, 41 deletions
diff --git a/vm/vm_object.c b/vm/vm_object.c
index 0dc3d540..c238cce4 100644
--- a/vm/vm_object.c
+++ b/vm/vm_object.c
@@ -44,6 +44,7 @@
#include <ipc/ipc_space.h>
#include <kern/assert.h>
#include <kern/debug.h>
+#include <kern/mach.server.h>
#include <kern/lock.h>
#include <kern/queue.h>
#include <kern/xpr.h>
@@ -182,7 +183,7 @@ vm_object_t kernel_object = &kernel_object_store;
*/
queue_head_t vm_object_cached_list;
-decl_simple_lock_data(,vm_object_cached_lock_data)
+def_simple_lock_data(static,vm_object_cached_lock_data)
#define vm_object_cache_lock() \
simple_lock(&vm_object_cached_lock_data)
@@ -198,7 +199,7 @@ decl_simple_lock_data(,vm_object_cached_lock_data)
*/
int vm_object_cached_pages;
-decl_simple_lock_data(,vm_object_cached_pages_lock_data)
+def_simple_lock_data(static,vm_object_cached_pages_lock_data)
/*
* Virtual memory objects are initialized from
@@ -226,7 +227,7 @@ static void _vm_object_setup(
object->size = size;
}
-vm_object_t _vm_object_allocate(
+static vm_object_t _vm_object_allocate(
vm_size_t size)
{
vm_object_t object;
@@ -725,7 +726,7 @@ void memory_object_release(
* In/out conditions:
* The object is locked on entry and exit.
*/
-void vm_object_abort_activity(
+static void vm_object_abort_activity(
vm_object_t object)
{
vm_page_t p;
@@ -1288,7 +1289,7 @@ boolean_t vm_object_copy_temporary(
* If the return value indicates an error, this parameter
* is not valid.
*/
-kern_return_t vm_object_copy_call(
+static kern_return_t vm_object_copy_call(
vm_object_t src_object,
vm_offset_t src_offset,
vm_size_t size,
@@ -2686,14 +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 the second object is NULL -
- * if it's not, 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
@@ -2703,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(
@@ -2713,28 +2722,60 @@ 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;
- if (next_object != VM_OBJECT_NULL) {
+ if (prev_object == next_object) {
+ /*
+ * If neither object actually exists,
+ * the offsets don't matter.
+ */
+ if (prev_object == VM_OBJECT_NULL) {
+ *new_object = VM_OBJECT_NULL;
+ *new_offset = 0;
+ return TRUE;
+ }
+
+ 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 (prev_object == VM_OBJECT_NULL) {
- return TRUE;
+ if (next_object != VM_OBJECT_NULL) {
+ /*
+ * Don't know how to merge two different
+ * objects yet.
+ */
+ if (prev_object != VM_OBJECT_NULL)
+ return FALSE;
+
+ object = next_object;
+ } else {
+ object = prev_object;
}
- vm_object_lock(prev_object);
+ vm_object_lock(object);
/*
* Try to collapse the object first
*/
- vm_object_collapse(prev_object);
+ vm_object_collapse(object);
/*
* Can't coalesce if pages not mapped to
- * prev_entry may be in use anyway:
+ * the object may be in use anyway:
* . more than one reference
* . paged out
* . shadows another object
@@ -2742,33 +2783,55 @@ boolean_t vm_object_coalesce(
* . paging references (pages might be in page-list)
*/
- if ((prev_object->ref_count > 1) ||
- prev_object->pager_created ||
- prev_object->used_for_pageout ||
- (prev_object->shadow != VM_OBJECT_NULL) ||
- (prev_object->copy != VM_OBJECT_NULL) ||
- (prev_object->paging_in_progress != 0)) {
- vm_object_unlock(prev_object);
+ if ((object->ref_count > 1) ||
+ object->pager_created ||
+ object->used_for_pageout ||
+ (object->shadow != VM_OBJECT_NULL) ||
+ (object->copy != VM_OBJECT_NULL) ||
+ (object->paging_in_progress != 0)) {
+ vm_object_unlock(object);
return FALSE;
}
- /*
- * Remove any pages that may still be in the object from
- * a previous deallocation.
- */
-
- vm_object_page_remove(prev_object,
+ if (object == prev_object) {
+ /*
+ * Remove any pages that may still be in
+ * the object from a previous deallocation.
+ */
+ vm_object_page_remove(object,
prev_offset + prev_size,
prev_offset + prev_size + next_size);
+ /*
+ * Extend the object if necessary.
+ */
+ newsize = prev_offset + prev_size + next_size;
+ if (newsize > object->size)
+ object->size = newsize;
- /*
- * Extend the object if necessary.
- */
- newsize = prev_offset + prev_size + next_size;
- if (newsize > prev_object->size)
- prev_object->size = newsize;
+ *new_offset = prev_offset;
+ } else {
+ /*
+ * Check if we have enough space in the object
+ * offset space to insert the new mapping before
+ * the existing one.
+ */
+ if (next_offset < prev_size) {
+ vm_object_unlock(object);
+ return FALSE;
+ }
+ /*
+ * Remove any pages that may still be in
+ * the object from a previous deallocation.
+ */
+ vm_object_page_remove(object,
+ next_offset - prev_size,
+ next_offset);
- vm_object_unlock(prev_object);
+ *new_offset = next_offset - prev_size;
+ }
+
+ vm_object_unlock(object);
+ *new_object = object;
return TRUE;
}