diff options
Diffstat (limited to 'vm')
-rw-r--r-- | vm/vm_map.c | 11 | ||||
-rw-r--r-- | vm/vm_object.c | 53 | ||||
-rw-r--r-- | vm/vm_object.h | 4 |
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); |