Changeset View
Standalone View
vm_map.c
Show First 20 Lines • Show All 2,053 Lines • ▼ Show 20 Lines | vm_map_simplify_entry(vm_map_t map, vm_map_entry_t entry) | ||||
next = entry->next; | next = entry->next; | ||||
if (vm_map_mergeable_neighbors(entry, next)) { | if (vm_map_mergeable_neighbors(entry, next)) { | ||||
vm_map_entry_unlink(map, next, UNLINK_MERGE_PREV); | vm_map_entry_unlink(map, next, UNLINK_MERGE_PREV); | ||||
vm_map_merged_neighbor_dispose(map, next); | vm_map_merged_neighbor_dispose(map, next); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* vm_map_entry_attach_backing_object: | |||||
* | |||||
* Allocate an object to back a map entry. | |||||
*/ | |||||
static inline void | |||||
vm_map_entry_attach_backing_object(vm_map_entry_t entry) | |||||
{ | |||||
vm_object_t object; | |||||
KASSERT(entry->object.vm_object == NULL, | |||||
kib: Assert that entry->object.vm_object == NULL.
Assert locks. | |||||
Not Done Inline ActionsYou did not asserted that the map is locked there. kib: You did not asserted that the map is locked there. | |||||
Done Inline ActionsThere is no map here. I could assert something in the caller, or pass a map here so that I could assert that it is locked. In the case of the call from *_fork, I'm not sure which map I would assert as locked. dougm: There is no map here. I could assert something in the caller, or pass a map here so that I… | |||||
Not Done Inline ActionsThat would be the map which owns the entry. But ok, I think it is fine to not add an argument only used for assert. kib: That would be the map which owns the entry. But ok, I think it is fine to not add an argument… | |||||
("map entry %p has backing object", entry)); | |||||
KASSERT((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0, | |||||
("map entry %p is a submap", entry)); | |||||
object = vm_object_allocate(OBJT_DEFAULT, | |||||
atop(entry->end - entry->start)); | |||||
entry->object.vm_object = object; | |||||
entry->offset = 0; | |||||
if (entry->cred != NULL) { | |||||
object->cred = entry->cred; | |||||
object->charge = entry->end - entry->start; | |||||
entry->cred = NULL; | |||||
} | |||||
} | |||||
/* | |||||
* vm_map_entry_find_backing_object: | |||||
* | |||||
* If there is no object backing this entry, we might as well create one | |||||
* now. If we defer it, an object can get created after the map is | |||||
* clipped, and individual objects will be created for the split-up map. | |||||
* This is a bit of a hack, but is also about the best place to put this | |||||
* improvement. | |||||
*/ | |||||
Done Inline ActionsAssert locks. Assert that the entry is not a submap. kib: Assert locks. Assert that the entry is not a submap. | |||||
static inline void | |||||
vm_map_entry_find_backing_object(vm_map_t map, vm_map_entry_t entry) | |||||
{ | |||||
VM_MAP_ASSERT_LOCKED(map); | |||||
KASSERT((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0, | |||||
Done Inline ActionsUse the opportunity to fix indentation of these two lines. kib: Use the opportunity to fix indentation of these two lines. | |||||
("map entry %p is a submap", entry)); | |||||
if (entry->object.vm_object == NULL && !map->system_map && | |||||
(entry->eflags & MAP_ENTRY_GUARD) == 0) | |||||
vm_map_entry_attach_backing_object(entry); | |||||
else if (entry->object.vm_object != NULL && | |||||
((entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) && | |||||
entry->cred != NULL) { | |||||
VM_OBJECT_WLOCK(entry->object.vm_object); | |||||
KASSERT(entry->object.vm_object->cred == NULL, | |||||
("OVERCOMMIT: %s: both cred e %p", __func__, entry)); | |||||
entry->object.vm_object->cred = entry->cred; | |||||
entry->object.vm_object->charge = entry->end - entry->start; | |||||
VM_OBJECT_WUNLOCK(entry->object.vm_object); | |||||
entry->cred = NULL; | |||||
} | |||||
} | |||||
/* | |||||
* vm_map_clip_start: [ internal use only ] | * vm_map_clip_start: [ internal use only ] | ||||
* | * | ||||
* Asserts that the given entry begins at or after | * Asserts that the given entry begins at or after | ||||
* the specified address; if necessary, | * the specified address; if necessary, | ||||
* it splits the entry into two. | * it splits the entry into two. | ||||
*/ | */ | ||||
#define vm_map_clip_start(map, entry, startaddr) \ | static inline void | ||||
Done Inline ActionsMay be convert this to static function (optionally inline) ? kib: May be convert this to static function (optionally inline) ? | |||||
{ \ | vm_map_clip_start(vm_map_t map, vm_map_entry_t entry, vm_offset_t start) | ||||
if (startaddr > entry->start) \ | { | ||||
_vm_map_clip_start(map, entry, startaddr); \ | if (start > entry->start) | ||||
_vm_map_clip_start(map, entry, start); | |||||
} | } | ||||
/* | /* | ||||
* This routine is called only when it is known that | * This routine is called only when it is known that | ||||
* the entry must be split. | * the entry must be split. | ||||
*/ | */ | ||||
static void | static void | ||||
_vm_map_clip_start(vm_map_t map, vm_map_entry_t entry, vm_offset_t start) | _vm_map_clip_start(vm_map_t map, vm_map_entry_t entry, vm_offset_t start) | ||||
kibUnsubmitted Done Inline ActionsDo we need this function standalone ? If vm_map_clip_start() do at the very beginning if(start <= entry->start) return; and then put the body of the _vm_map_clip_start(), it seems to make the code simpler. I believe the old structure was for some quite non-optimizing compiler. kib: Do we need this function standalone ? If vm_map_clip_start() do at the very beginning
``` if… | |||||
Done Inline ActionsThe comment doesn't really make sense anymore; what does "now" mean? markj: The comment doesn't really make sense anymore; what does "now" mean? | |||||
Done Inline ActionsI have tried to make it more sensible. dougm: I have tried to make it more sensible. | |||||
{ | { | ||||
vm_map_entry_t new_entry; | vm_map_entry_t new_entry; | ||||
VM_MAP_ASSERT_LOCKED(map); | VM_MAP_ASSERT_LOCKED(map); | ||||
KASSERT(entry->end > start && entry->start < start, | KASSERT(entry->end > start && entry->start < start, | ||||
("_vm_map_clip_start: invalid clip of entry %p", entry)); | ("_vm_map_clip_start: invalid clip of entry %p", entry)); | ||||
Done Inline ActionsIt is no longer _vm_map_clip_start, remove prefix '_'. kib: It is no longer _vm_map_clip_start, remove prefix '_'. | |||||
/* | /* | ||||
Done Inline ActionsCan't the assertion come before the check? markj: Can't the assertion come before the check? | |||||
Done Inline ActionsOkay. dougm: Okay. | |||||
* Split off the front portion -- note that we must insert the new | * Split off the front portion -- note that we must insert the new | ||||
* entry BEFORE this one, so that this entry has the specified | * entry BEFORE this one, so that this entry has the specified | ||||
* starting address. | * starting address. | ||||
*/ | */ | ||||
vm_map_simplify_entry(map, entry); | vm_map_simplify_entry(map, entry); | ||||
vm_map_entry_find_backing_object(map, entry); | |||||
/* | |||||
* If there is no object backing this entry, we might as well create | |||||
* one now. If we defer it, an object can get created after the map | |||||
* is clipped, and individual objects will be created for the split-up | |||||
* map. This is a bit of a hack, but is also about the best place to | |||||
* put this improvement. | |||||
*/ | |||||
if (entry->object.vm_object == NULL && !map->system_map && | |||||
(entry->eflags & MAP_ENTRY_GUARD) == 0) { | |||||
vm_object_t object; | |||||
object = vm_object_allocate(OBJT_DEFAULT, | |||||
atop(entry->end - entry->start)); | |||||
entry->object.vm_object = object; | |||||
entry->offset = 0; | |||||
if (entry->cred != NULL) { | |||||
object->cred = entry->cred; | |||||
object->charge = entry->end - entry->start; | |||||
entry->cred = NULL; | |||||
} | |||||
} else if (entry->object.vm_object != NULL && | |||||
((entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) && | |||||
entry->cred != NULL) { | |||||
VM_OBJECT_WLOCK(entry->object.vm_object); | |||||
KASSERT(entry->object.vm_object->cred == NULL, | |||||
("OVERCOMMIT: vm_entry_clip_start: both cred e %p", entry)); | |||||
entry->object.vm_object->cred = entry->cred; | |||||
entry->object.vm_object->charge = entry->end - entry->start; | |||||
VM_OBJECT_WUNLOCK(entry->object.vm_object); | |||||
entry->cred = NULL; | |||||
} | |||||
new_entry = vm_map_entry_create(map); | new_entry = vm_map_entry_create(map); | ||||
*new_entry = *entry; | *new_entry = *entry; | ||||
Not Done Inline ActionsI don't really understand the purpose of lifting this portion out into a separate function: it doesn't eliminate any duplication. I also find it hard to reason about what this function is supposed to do given its name. markj: I don't really understand the purpose of lifting this portion out into a separate function: it… | |||||
Done Inline ActionsThe code appears in both clip_start and clip_end functions, so that duplication is removed. I could change the name vm_map_entry_find_backing_object, but if I drop "vm_map_entry", Alan will object, and if I drop "backing_object", I'm dropping what the comment that precedes this code block says it's about. It either creates a backing object, or uses one already there. Maybe I can do better than "find"? dougm: The code appears in both clip_start and clip_end functions, so that duplication is removed.
I… | |||||
Not Done Inline ActionsWhat about vm_map_entry_clip_object() ? kib: What about vm_map_entry_clip_object() ? | |||||
Done Inline ActionsI'm willing to do it, if that will satisfy everyone, but I don't think that name makes much sense. It seems like the actual clipping depends on a 'start' or 'end' value that isn't passed to this function. dougm: I'm willing to do it, if that will satisfy everyone, but I don't think that name makes much… | |||||
Not Done Inline Actionsvm_map_entry_charge_object()? markj: vm_map_entry_charge_object()? | |||||
new_entry->end = start; | new_entry->end = start; | ||||
entry->offset += (start - entry->start); | entry->offset += (start - entry->start); | ||||
entry->start = start; | entry->start = start; | ||||
if (new_entry->cred != NULL) | if (new_entry->cred != NULL) | ||||
crhold(entry->cred); | crhold(entry->cred); | ||||
vm_map_entry_link(map, new_entry); | vm_map_entry_link(map, new_entry); | ||||
if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { | if ((entry->eflags & MAP_ENTRY_IS_SUB_MAP) == 0) { | ||||
vm_object_reference(new_entry->object.vm_object); | vm_object_reference(new_entry->object.vm_object); | ||||
vm_map_entry_set_vnode_text(new_entry, true); | vm_map_entry_set_vnode_text(new_entry, true); | ||||
/* | /* | ||||
* The object->un_pager.vnp.writemappings for the | * The object->un_pager.vnp.writemappings for the | ||||
* object of MAP_ENTRY_VN_WRITECNT type entry shall be | * object of MAP_ENTRY_VN_WRITECNT type entry shall be | ||||
* kept as is here. The virtual pages are | * kept as is here. The virtual pages are | ||||
* re-distributed among the clipped entries, so the sum is | * re-distributed among the clipped entries, so the sum is | ||||
* left the same. | * left the same. | ||||
*/ | */ | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* | |||||
*/ | |||||
static inline vm_map_entry_t | |||||
vm_map_lookup_clip_start(vm_map_t map, vm_offset_t start, bool modify, | |||||
bool modify) | |||||
{ | |||||
vm_map_entry_t entry; | |||||
if (!vm_map_lookup_entry(map, start, &entry)) | |||||
entry = entry->next; | |||||
else if (modify) | |||||
vm_map_clip_start(map, entry, start); | |||||
return (entry); | |||||
} | |||||
/* | |||||
* vm_map_clip_end: [ internal use only ] | * vm_map_clip_end: [ internal use only ] | ||||
* | * | ||||
* Asserts that the given entry ends at or before | * Asserts that the given entry ends at or before | ||||
* the specified address; if necessary, | * the specified address; if necessary, | ||||
* it splits the entry into two. | * it splits the entry into two. | ||||
*/ | */ | ||||
#define vm_map_clip_end(map, entry, endaddr) \ | static inline void | ||||
{ \ | vm_map_clip_end(vm_map_t map, vm_map_entry_t entry, vm_offset_t end) | ||||
if ((endaddr) < (entry->end)) \ | { | ||||
Not Done Inline ActionsThis can't compile. alc: This can't compile. | |||||
_vm_map_clip_end((map), (entry), (endaddr)); \ | if (end < entry->end) | ||||
_vm_map_clip_end(map, entry, end); | |||||
} | } | ||||
/* | /* | ||||
* This routine is called only when it is known that | * This routine is called only when it is known that | ||||
* the entry must be split. | * the entry must be split. | ||||
*/ | */ | ||||
static void | static void | ||||
_vm_map_clip_end(vm_map_t map, vm_map_entry_t entry, vm_offset_t end) | _vm_map_clip_end(vm_map_t map, vm_map_entry_t entry, vm_offset_t end) | ||||
{ | { | ||||
vm_map_entry_t new_entry; | vm_map_entry_t new_entry; | ||||
VM_MAP_ASSERT_LOCKED(map); | VM_MAP_ASSERT_LOCKED(map); | ||||
KASSERT(entry->start < end && entry->end > end, | KASSERT(entry->start < end && entry->end > end, | ||||
("_vm_map_clip_end: invalid clip of entry %p", entry)); | ("_vm_map_clip_end: invalid clip of entry %p", entry)); | ||||
Done Inline ActionsSame there. kib: Same there. | |||||
/* | /* | ||||
* If there is no object backing this entry, we might as well create | |||||
* one now. If we defer it, an object can get created after the map | |||||
* is clipped, and individual objects will be created for the split-up | |||||
* map. This is a bit of a hack, but is also about the best place to | |||||
* put this improvement. | |||||
*/ | |||||
if (entry->object.vm_object == NULL && !map->system_map && | |||||
(entry->eflags & MAP_ENTRY_GUARD) == 0) { | |||||
vm_object_t object; | |||||
object = vm_object_allocate(OBJT_DEFAULT, | |||||
atop(entry->end - entry->start)); | |||||
entry->object.vm_object = object; | |||||
entry->offset = 0; | |||||
if (entry->cred != NULL) { | |||||
object->cred = entry->cred; | |||||
object->charge = entry->end - entry->start; | |||||
entry->cred = NULL; | |||||
} | |||||
} else if (entry->object.vm_object != NULL && | |||||
((entry->eflags & MAP_ENTRY_NEEDS_COPY) == 0) && | |||||
entry->cred != NULL) { | |||||
VM_OBJECT_WLOCK(entry->object.vm_object); | |||||
KASSERT(entry->object.vm_object->cred == NULL, | |||||
("OVERCOMMIT: vm_entry_clip_end: both cred e %p", entry)); | |||||
entry->object.vm_object->cred = entry->cred; | |||||
entry->object.vm_object->charge = entry->end - entry->start; | |||||
VM_OBJECT_WUNLOCK(entry->object.vm_object); | |||||
entry->cred = NULL; | |||||
} | |||||
/* | |||||
* Create a new entry and insert it AFTER the specified entry | * Create a new entry and insert it AFTER the specified entry | ||||
*/ | */ | ||||
vm_map_entry_find_backing_object(map, entry); | |||||
new_entry = vm_map_entry_create(map); | new_entry = vm_map_entry_create(map); | ||||
*new_entry = *entry; | *new_entry = *entry; | ||||
new_entry->start = entry->end = end; | new_entry->start = entry->end = end; | ||||
new_entry->offset += (end - entry->start); | new_entry->offset += (end - entry->start); | ||||
if (new_entry->cred != NULL) | if (new_entry->cred != NULL) | ||||
crhold(entry->cred); | crhold(entry->cred); | ||||
Show All 38 Lines | vm_map_submap( | ||||
vm_map_lock(submap); | vm_map_lock(submap); | ||||
submap->flags |= MAP_IS_SUB_MAP; | submap->flags |= MAP_IS_SUB_MAP; | ||||
vm_map_unlock(submap); | vm_map_unlock(submap); | ||||
vm_map_lock(map); | vm_map_lock(map); | ||||
VM_MAP_RANGE_CHECK(map, start, end); | VM_MAP_RANGE_CHECK(map, start, end); | ||||
if (vm_map_lookup_entry(map, start, &entry)) { | entry = vm_map_lookup_clip_start(map, start, true); | ||||
vm_map_clip_start(map, entry, start); | |||||
} else | |||||
entry = entry->next; | |||||
vm_map_clip_end(map, entry, end); | vm_map_clip_end(map, entry, end); | ||||
if ((entry->start == start) && (entry->end == end) && | if ((entry->start == start) && (entry->end == end) && | ||||
((entry->eflags & MAP_ENTRY_COW) == 0) && | ((entry->eflags & MAP_ENTRY_COW) == 0) && | ||||
(entry->object.vm_object == NULL)) { | (entry->object.vm_object == NULL)) { | ||||
entry->object.sub_map = submap; | entry->object.sub_map = submap; | ||||
entry->eflags |= MAP_ENTRY_IS_SUB_MAP; | entry->eflags |= MAP_ENTRY_IS_SUB_MAP; | ||||
result = KERN_SUCCESS; | result = KERN_SUCCESS; | ||||
▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | again: | ||||
* need to fault pages into the map and will drop the map lock while | * need to fault pages into the map and will drop the map lock while | ||||
* doing so, and the VM object may end up in an inconsistent state if we | * doing so, and the VM object may end up in an inconsistent state if we | ||||
* update the protection on the map entry in between faults. | * update the protection on the map entry in between faults. | ||||
*/ | */ | ||||
vm_map_wait_busy(map); | vm_map_wait_busy(map); | ||||
VM_MAP_RANGE_CHECK(map, start, end); | VM_MAP_RANGE_CHECK(map, start, end); | ||||
if (vm_map_lookup_entry(map, start, &entry)) { | entry = vm_map_lookup_clip_start(map, start, true); | ||||
vm_map_clip_start(map, entry, start); | |||||
} else { | |||||
entry = entry->next; | |||||
} | |||||
/* | /* | ||||
* Make a first pass to check for protection violations. | * Make a first pass to check for protection violations. | ||||
*/ | */ | ||||
for (current = entry; current->start < end; current = current->next) { | for (current = entry; current->start < end; current = current->next) { | ||||
if ((current->eflags & MAP_ENTRY_GUARD) != 0) | if ((current->eflags & MAP_ENTRY_GUARD) != 0) | ||||
continue; | continue; | ||||
if (current->eflags & MAP_ENTRY_IS_SUB_MAP) { | if (current->eflags & MAP_ENTRY_IS_SUB_MAP) { | ||||
▲ Show 20 Lines • Show All 171 Lines • ▼ Show 20 Lines | vm_map_madvise( | ||||
default: | default: | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
/* | /* | ||||
* Locate starting entry and clip if necessary. | * Locate starting entry and clip if necessary. | ||||
*/ | */ | ||||
VM_MAP_RANGE_CHECK(map, start, end); | VM_MAP_RANGE_CHECK(map, start, end); | ||||
if (vm_map_lookup_entry(map, start, &entry)) { | entry = vm_map_lookup_clip_start(map, start, modify_map); | ||||
Done Inline ActionsI prefer to either have {} in both branches for if(), or to not have {} in both. kib: I prefer to either have {} in both branches for if(), or to not have {} in both. | |||||
if (modify_map) | |||||
vm_map_clip_start(map, entry, start); | |||||
} else { | |||||
entry = entry->next; | |||||
} | |||||
if (modify_map) { | if (modify_map) { | ||||
/* | /* | ||||
* madvise behaviors that are implemented in the vm_map_entry. | * madvise behaviors that are implemented in the vm_map_entry. | ||||
* | * | ||||
* We clip the vm_map_entry so that behavioral changes are | * We clip the vm_map_entry so that behavioral changes are | ||||
* limited to the specified address range. | * limited to the specified address range. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 114 Lines • ▼ Show 20 Lines | |||||
* affects how the map will be shared with | * affects how the map will be shared with | ||||
* child maps at the time of vmspace_fork. | * child maps at the time of vmspace_fork. | ||||
*/ | */ | ||||
int | int | ||||
vm_map_inherit(vm_map_t map, vm_offset_t start, vm_offset_t end, | vm_map_inherit(vm_map_t map, vm_offset_t start, vm_offset_t end, | ||||
vm_inherit_t new_inheritance) | vm_inherit_t new_inheritance) | ||||
{ | { | ||||
vm_map_entry_t entry; | vm_map_entry_t entry; | ||||
vm_map_entry_t temp_entry; | |||||
switch (new_inheritance) { | switch (new_inheritance) { | ||||
case VM_INHERIT_NONE: | case VM_INHERIT_NONE: | ||||
case VM_INHERIT_COPY: | case VM_INHERIT_COPY: | ||||
case VM_INHERIT_SHARE: | case VM_INHERIT_SHARE: | ||||
case VM_INHERIT_ZERO: | case VM_INHERIT_ZERO: | ||||
break; | break; | ||||
default: | default: | ||||
return (KERN_INVALID_ARGUMENT); | return (KERN_INVALID_ARGUMENT); | ||||
} | } | ||||
if (start == end) | if (start == end) | ||||
return (KERN_SUCCESS); | return (KERN_SUCCESS); | ||||
vm_map_lock(map); | vm_map_lock(map); | ||||
VM_MAP_RANGE_CHECK(map, start, end); | VM_MAP_RANGE_CHECK(map, start, end); | ||||
if (vm_map_lookup_entry(map, start, &temp_entry)) { | entry = vm_map_lookup_clip_start(map, start, true); | ||||
entry = temp_entry; | |||||
vm_map_clip_start(map, entry, start); | |||||
} else | |||||
entry = temp_entry->next; | |||||
while (entry->start < end) { | while (entry->start < end) { | ||||
vm_map_clip_end(map, entry, end); | vm_map_clip_end(map, entry, end); | ||||
if ((entry->eflags & MAP_ENTRY_GUARD) == 0 || | if ((entry->eflags & MAP_ENTRY_GUARD) == 0 || | ||||
new_inheritance != VM_INHERIT_ZERO) | new_inheritance != VM_INHERIT_ZERO) | ||||
entry->inheritance = new_inheritance; | entry->inheritance = new_inheritance; | ||||
vm_map_simplify_entry(map, entry); | vm_map_simplify_entry(map, entry); | ||||
entry = entry->next; | entry = entry->next; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | if (entry->eflags & MAP_ENTRY_IN_TRANSITION) { | ||||
first_entry = tmp_entry; | first_entry = tmp_entry; | ||||
else | else | ||||
first_entry = NULL; | first_entry = NULL; | ||||
entry = tmp_entry; | entry = tmp_entry; | ||||
} | } | ||||
last_timestamp = map->timestamp; | last_timestamp = map->timestamp; | ||||
continue; | continue; | ||||
} | } | ||||
vm_map_clip_start(map, entry, start); | entry = vm_map_lookup_clip_start(map, start, true); | ||||
vm_map_clip_end(map, entry, end); | vm_map_clip_end(map, entry, end); | ||||
/* | /* | ||||
* Mark the entry in case the map lock is released. (See | * Mark the entry in case the map lock is released. (See | ||||
* above.) | * above.) | ||||
*/ | */ | ||||
KASSERT((entry->eflags & MAP_ENTRY_IN_TRANSITION) == 0 && | KASSERT((entry->eflags & MAP_ENTRY_IN_TRANSITION) == 0 && | ||||
entry->wiring_thread == NULL, | entry->wiring_thread == NULL, | ||||
("owned map entry %p", entry)); | ("owned map entry %p", entry)); | ||||
▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | if (entry->eflags & MAP_ENTRY_IN_TRANSITION) { | ||||
first_entry = tmp_entry; | first_entry = tmp_entry; | ||||
else | else | ||||
first_entry = NULL; | first_entry = NULL; | ||||
entry = tmp_entry; | entry = tmp_entry; | ||||
} | } | ||||
last_timestamp = map->timestamp; | last_timestamp = map->timestamp; | ||||
continue; | continue; | ||||
} | } | ||||
vm_map_clip_start(map, entry, start); | entry = vm_map_lookup_clip_start(map, start, true); | ||||
vm_map_clip_end(map, entry, end); | vm_map_clip_end(map, entry, end); | ||||
/* | /* | ||||
* Mark the entry in case the map lock is released. (See | * Mark the entry in case the map lock is released. (See | ||||
* above.) | * above.) | ||||
*/ | */ | ||||
KASSERT((entry->eflags & MAP_ENTRY_IN_TRANSITION) == 0 && | KASSERT((entry->eflags & MAP_ENTRY_IN_TRANSITION) == 0 && | ||||
entry->wiring_thread == NULL, | entry->wiring_thread == NULL, | ||||
("owned map entry %p", entry)); | ("owned map entry %p", entry)); | ||||
▲ Show 20 Lines • Show All 390 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* Deallocates the given address range from the target | * Deallocates the given address range from the target | ||||
* map. | * map. | ||||
*/ | */ | ||||
int | int | ||||
vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end) | vm_map_delete(vm_map_t map, vm_offset_t start, vm_offset_t end) | ||||
{ | { | ||||
vm_map_entry_t entry; | vm_map_entry_t entry; | ||||
vm_map_entry_t first_entry; | |||||
VM_MAP_ASSERT_LOCKED(map); | VM_MAP_ASSERT_LOCKED(map); | ||||
if (start == end) | if (start == end) | ||||
return (KERN_SUCCESS); | return (KERN_SUCCESS); | ||||
/* | /* | ||||
* Find the start of the region, and clip it | * Find the start of the region, and clip it | ||||
*/ | */ | ||||
if (!vm_map_lookup_entry(map, start, &first_entry)) | entry = vm_map_lookup_clip_start(map, start, true); | ||||
entry = first_entry->next; | |||||
else { | |||||
entry = first_entry; | |||||
vm_map_clip_start(map, entry, start); | |||||
} | |||||
/* | /* | ||||
* Step through all entries in this region | * Step through all entries in this region | ||||
*/ | */ | ||||
while (entry->start < end) { | while (entry->start < end) { | ||||
vm_map_entry_t next; | vm_map_entry_t next; | ||||
/* | /* | ||||
* Wait for wiring or unwiring of an entry to complete. | * Wait for wiring or unwiring of an entry to complete. | ||||
* Also wait for any system wirings to disappear on | * Also wait for any system wirings to disappear on | ||||
* user maps. | * user maps. | ||||
*/ | */ | ||||
if ((entry->eflags & MAP_ENTRY_IN_TRANSITION) != 0 || | if ((entry->eflags & MAP_ENTRY_IN_TRANSITION) != 0 || | ||||
(vm_map_pmap(map) != kernel_pmap && | (vm_map_pmap(map) != kernel_pmap && | ||||
vm_map_entry_system_wired_count(entry) != 0)) { | vm_map_entry_system_wired_count(entry) != 0)) { | ||||
unsigned int last_timestamp; | unsigned int last_timestamp; | ||||
vm_offset_t saved_start; | vm_offset_t saved_start; | ||||
vm_map_entry_t tmp_entry; | |||||
saved_start = entry->start; | saved_start = entry->start; | ||||
entry->eflags |= MAP_ENTRY_NEEDS_WAKEUP; | entry->eflags |= MAP_ENTRY_NEEDS_WAKEUP; | ||||
last_timestamp = map->timestamp; | last_timestamp = map->timestamp; | ||||
(void) vm_map_unlock_and_wait(map, 0); | (void) vm_map_unlock_and_wait(map, 0); | ||||
vm_map_lock(map); | vm_map_lock(map); | ||||
if (last_timestamp + 1 != map->timestamp) { | if (last_timestamp + 1 != map->timestamp) { | ||||
/* | /* | ||||
* Look again for the entry because the map was | * Look again for the entry because the map was | ||||
* modified while it was unlocked. | * modified while it was unlocked. | ||||
* Specifically, the entry may have been | * Specifically, the entry may have been | ||||
* clipped, merged, or deleted. | * clipped, merged, or deleted. | ||||
*/ | */ | ||||
if (!vm_map_lookup_entry(map, saved_start, | entry = vm_map_lookup_clip_start(map, | ||||
&tmp_entry)) | saved_start, true); | ||||
entry = tmp_entry->next; | |||||
else { | |||||
entry = tmp_entry; | |||||
vm_map_clip_start(map, entry, | |||||
saved_start); | |||||
} | } | ||||
} | |||||
continue; | continue; | ||||
} | } | ||||
vm_map_clip_end(map, entry, end); | vm_map_clip_end(map, entry, end); | ||||
next = entry->next; | next = entry->next; | ||||
/* | /* | ||||
* Unwire before removing addresses from the pmap; otherwise, | * Unwire before removing addresses from the pmap; otherwise, | ||||
▲ Show 20 Lines • Show All 315 Lines • ▼ Show 20 Lines | case VM_INHERIT_NONE: | ||||
break; | break; | ||||
case VM_INHERIT_SHARE: | case VM_INHERIT_SHARE: | ||||
/* | /* | ||||
* Clone the entry, creating the shared object if necessary. | * Clone the entry, creating the shared object if necessary. | ||||
*/ | */ | ||||
object = old_entry->object.vm_object; | object = old_entry->object.vm_object; | ||||
if (object == NULL) { | if (object == NULL) { | ||||
object = vm_object_allocate(OBJT_DEFAULT, | vm_map_entry_attach_backing_object(old_entry); | ||||
atop(old_entry->end - old_entry->start)); | object = old_entry->object.vm_object; | ||||
Not Done Inline ActionsIMO it would be more natural to return the new object from vm_map_entry_attach_backing_object(). markj: IMO it would be more natural to return the new object from vm_map_entry_attach_backing_object(). | |||||
Done Inline ActionsIn one place, I would cast away the returned result. In the other, I would get to drop one assignment line, but I would also need to shorten the function name to fit in 80 columns after doing proper line wrapping. dougm: In one place, I would cast away the returned result. In the other, I would get to drop one… | |||||
Not Done Inline ActionsMaybe call it vm_map_entry_back()? That is admittedly terse. Otherwise I would remove "_backing". I think it's implied. markj: Maybe call it vm_map_entry_back()? That is admittedly terse.
Otherwise I would remove… | |||||
Not Done Inline Actions... implied by virtue of the fact that the function doesn't take an object parameter. markj: ... implied by virtue of the fact that the function doesn't take an object parameter. | |||||
old_entry->object.vm_object = object; | |||||
old_entry->offset = 0; | |||||
if (old_entry->cred != NULL) { | |||||
object->cred = old_entry->cred; | |||||
object->charge = old_entry->end - | |||||
old_entry->start; | |||||
old_entry->cred = NULL; | |||||
} | |||||
} | } | ||||
/* | /* | ||||
* Add the reference before calling vm_object_shadow | * Add the reference before calling vm_object_shadow | ||||
* to insure that a shadow object is created. | * to insure that a shadow object is created. | ||||
*/ | */ | ||||
vm_object_reference(object); | vm_object_reference(object); | ||||
if (old_entry->eflags & MAP_ENTRY_NEEDS_COPY) { | if (old_entry->eflags & MAP_ENTRY_NEEDS_COPY) { | ||||
▲ Show 20 Lines • Show All 963 Lines • Show Last 20 Lines |
Assert that entry->object.vm_object == NULL.
Assert locks.