svn commit: r350155 - head/sys/vm
Doug Moore
dougm at FreeBSD.org
Fri Jul 19 20:47:36 UTC 2019
Author: dougm
Date: Fri Jul 19 20:47:35 2019
New Revision: 350155
URL: https://svnweb.freebsd.org/changeset/base/350155
Log:
Define vm_map_entry_in_transition to handle an in-transition map
entry, combining code currently in vm_map_unwire and
vm_map_wire_locked into a single function, called by each of them for
entries in transition.
Discussed with: kib, markj
Reviewed by: alc
Approved by: kib, markj (mentors, implicit)
Tested by: pho
Differential Revision: https://reviews.freebsd.org/D20833
Modified:
head/sys/vm/vm_map.c
Modified: head/sys/vm/vm_map.c
==============================================================================
--- head/sys/vm/vm_map.c Fri Jul 19 20:04:31 2019 (r350154)
+++ head/sys/vm/vm_map.c Fri Jul 19 20:47:35 2019 (r350155)
@@ -2837,6 +2837,55 @@ vm_map_inherit(vm_map_t map, vm_offset_t start, vm_off
}
/*
+ * vm_map_entry_in_transition:
+ *
+ * Release the map lock, and sleep until the entry is no longer in
+ * transition. Awake and acquire the map lock. If the map changed while
+ * another held the lock, lookup a possibly-changed entry at or after the
+ * 'start' position of the old entry.
+ */
+static vm_map_entry_t
+vm_map_entry_in_transition(vm_map_t map, vm_offset_t in_start,
+ vm_offset_t *io_end, bool holes_ok, vm_map_entry_t in_entry)
+{
+ vm_map_entry_t entry;
+ vm_offset_t start;
+ u_int last_timestamp;
+
+ VM_MAP_ASSERT_LOCKED(map);
+ KASSERT((in_entry->eflags & MAP_ENTRY_IN_TRANSITION) != 0,
+ ("not in-tranition map entry %p", in_entry));
+ /*
+ * We have not yet clipped the entry.
+ */
+ start = MAX(in_start, in_entry->start);
+ in_entry->eflags |= MAP_ENTRY_NEEDS_WAKEUP;
+ last_timestamp = map->timestamp;
+ if (vm_map_unlock_and_wait(map, 0)) {
+ /*
+ * Allow interruption of user wiring/unwiring?
+ */
+ }
+ vm_map_lock(map);
+ if (last_timestamp + 1 == map->timestamp)
+ return (in_entry);
+
+ /*
+ * Look again for the entry because the map was modified while it was
+ * unlocked. Specifically, the entry may have been clipped, merged, or
+ * deleted.
+ */
+ if (!vm_map_lookup_entry(map, start, &entry)) {
+ if (!holes_ok) {
+ *io_end = start;
+ return (NULL);
+ }
+ entry = entry->next;
+ }
+ return (entry);
+}
+
+/*
* vm_map_unwire:
*
* Implements both kernel and user unwiring.
@@ -2845,11 +2894,9 @@ int
vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offset_t end,
int flags)
{
- vm_map_entry_t entry, first_entry, tmp_entry;
- vm_offset_t saved_start;
- unsigned int last_timestamp;
+ vm_map_entry_t entry, first_entry;
int rv;
- bool holes_ok, need_wakeup, user_unwire;
+ bool first_iteration, holes_ok, need_wakeup, user_unwire;
if (start == end)
return (KERN_SUCCESS);
@@ -2865,7 +2912,7 @@ vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offs
return (KERN_INVALID_ADDRESS);
}
}
- last_timestamp = map->timestamp;
+ first_iteration = true;
entry = first_entry;
rv = KERN_SUCCESS;
while (entry->start < end) {
@@ -2873,48 +2920,20 @@ vm_map_unwire(vm_map_t map, vm_offset_t start, vm_offs
/*
* We have not yet clipped the entry.
*/
- saved_start = (start >= entry->start) ? start :
- entry->start;
- entry->eflags |= MAP_ENTRY_NEEDS_WAKEUP;
- if (vm_map_unlock_and_wait(map, 0)) {
- /*
- * Allow interruption of user unwiring?
- */
- }
- vm_map_lock(map);
- if (last_timestamp+1 != map->timestamp) {
- /*
- * Look again for the entry because the map was
- * modified while it was unlocked.
- * Specifically, the entry may have been
- * clipped, merged, or deleted.
- */
- if (!vm_map_lookup_entry(map, saved_start,
- &tmp_entry)) {
- if (holes_ok)
- tmp_entry = tmp_entry->next;
- else {
- if (saved_start == start) {
- /*
- * First_entry has been deleted.
- */
- vm_map_unlock(map);
- return (KERN_INVALID_ADDRESS);
- }
- end = saved_start;
- rv = KERN_INVALID_ADDRESS;
- break;
- }
+ entry = vm_map_entry_in_transition(map, start, &end,
+ holes_ok, entry);
+ if (entry == NULL) {
+ if (first_iteration) {
+ vm_map_unlock(map);
+ return (KERN_INVALID_ADDRESS);
}
- if (entry == first_entry)
- first_entry = tmp_entry;
- else
- first_entry = NULL;
- entry = tmp_entry;
+ rv = KERN_INVALID_ADDRESS;
+ break;
}
- last_timestamp = map->timestamp;
+ first_entry = first_iteration ? entry : NULL;
continue;
}
+ first_iteration = false;
vm_map_clip_start(map, entry, start);
vm_map_clip_end(map, entry, end);
/*
@@ -3081,7 +3100,7 @@ vm_map_wire_locked(vm_map_t map, vm_offset_t start, vm
u_long npages;
u_int last_timestamp;
int rv;
- bool holes_ok, need_wakeup, user_wire;
+ bool first_iteration, holes_ok, need_wakeup, user_wire;
vm_prot_t prot;
VM_MAP_ASSERT_LOCKED(map);
@@ -3100,54 +3119,25 @@ vm_map_wire_locked(vm_map_t map, vm_offset_t start, vm
else
return (KERN_INVALID_ADDRESS);
}
- last_timestamp = map->timestamp;
+ first_iteration = true;
entry = first_entry;
while (entry->start < end) {
if (entry->eflags & MAP_ENTRY_IN_TRANSITION) {
/*
* We have not yet clipped the entry.
*/
- saved_start = (start >= entry->start) ? start :
- entry->start;
- entry->eflags |= MAP_ENTRY_NEEDS_WAKEUP;
- if (vm_map_unlock_and_wait(map, 0)) {
- /*
- * Allow interruption of user wiring?
- */
+ entry = vm_map_entry_in_transition(map, start, &end,
+ holes_ok, entry);
+ if (entry == NULL) {
+ if (first_iteration)
+ return (KERN_INVALID_ADDRESS);
+ rv = KERN_INVALID_ADDRESS;
+ goto done;
}
- vm_map_lock(map);
- if (last_timestamp + 1 != map->timestamp) {
- /*
- * Look again for the entry because the map was
- * modified while it was unlocked.
- * Specifically, the entry may have been
- * clipped, merged, or deleted.
- */
- if (!vm_map_lookup_entry(map, saved_start,
- &tmp_entry)) {
- if (holes_ok)
- tmp_entry = tmp_entry->next;
- else {
- if (saved_start == start) {
- /*
- * first_entry has been deleted.
- */
- return (KERN_INVALID_ADDRESS);
- }
- end = saved_start;
- rv = KERN_INVALID_ADDRESS;
- goto done;
- }
- }
- if (entry == first_entry)
- first_entry = tmp_entry;
- else
- first_entry = NULL;
- entry = tmp_entry;
- }
- last_timestamp = map->timestamp;
+ first_entry = first_iteration ? entry : NULL;
continue;
}
+ first_iteration = false;
vm_map_clip_start(map, entry, start);
vm_map_clip_end(map, entry, end);
/*
@@ -3185,6 +3175,7 @@ vm_map_wire_locked(vm_map_t map, vm_offset_t start, vm
*/
saved_start = entry->start;
saved_end = entry->end;
+ last_timestamp = map->timestamp;
vm_map_busy(map);
vm_map_unlock(map);
@@ -3230,7 +3221,6 @@ vm_map_wire_locked(vm_map_t map, vm_offset_t start, vm
entry = entry->next;
}
}
- last_timestamp = map->timestamp;
if (rv != KERN_SUCCESS) {
vm_map_wire_entry_failure(map, entry, faddr);
if (user_wire)
More information about the svn-src-all
mailing list