Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111831625
D20833.id59316.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D20833.id59316.diff
View Options
Index: vm_map.c
===================================================================
--- vm_map.c
+++ vm_map.c
@@ -2839,6 +2839,64 @@
}
/*
+ * vm_map_get_avail_entry:
+ *
+ * Get the first entry not less than start, or entry->start,
+ * once that entry is not in transition. Return NULL and
+ * set end if the entry comes after an unacceptible hole.
+ */
+static vm_map_entry_t
+vm_map_get_avail_entry(vm_map_t map, vm_offset_t start, vm_offset_t *end,
+ bool holes_ok, vm_map_entry_t entry, vm_map_entry_t *first_entry)
+{
+ unsigned int last_timestamp;
+ bool first_call;
+
+ first_call = entry == NULL;
+ for (;;) {
+ if (entry == NULL) {
+ if (!vm_map_lookup_entry(map, start, &entry)) {
+ if (!holes_ok) {
+ *end = start;
+ return (NULL);
+ }
+ entry = entry->next;
+ }
+ }
+ if (entry->start >= *end ||
+ (entry->eflags & MAP_ENTRY_IN_TRANSITION) == 0) {
+ if (first_call)
+ *first_entry = entry;
+ return (entry);
+ }
+
+ /*
+ * We have not yet clipped the entry.
+ */
+ start = ulmax(start, entry->start);
+ entry->eflags |= MAP_ENTRY_NEEDS_WAKEUP;
+ last_timestamp = map->timestamp;
+ 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.
+ */
+ entry = NULL;
+ }
+ if (!first_call)
+ *first_entry = NULL;
+ }
+}
+
+
+/*
* vm_map_unwire:
*
* Implements both kernel and user unwiring.
@@ -2847,74 +2905,25 @@
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;
- boolean_t need_wakeup, result, user_unwire;
+ boolean_t result;
+ bool holes_ok, need_wakeup, user_unwire;
if (start == end)
return (KERN_SUCCESS);
- user_unwire = (flags & VM_MAP_WIRE_USER) ? TRUE : FALSE;
+ user_unwire = (flags & VM_MAP_WIRE_USER) != 0;
+ holes_ok = (flags & VM_MAP_WIRE_HOLESOK) != 0;
vm_map_lock(map);
VM_MAP_RANGE_CHECK(map, start, end);
- if (!vm_map_lookup_entry(map, start, &first_entry)) {
- if (flags & VM_MAP_WIRE_HOLESOK)
- first_entry = first_entry->next;
- else {
- vm_map_unlock(map);
- return (KERN_INVALID_ADDRESS);
- }
+ entry = vm_map_get_avail_entry(map, start, &end, holes_ok,
+ NULL, &first_entry);
+ if (entry == NULL) {
+ vm_map_unlock(map);
+ return (KERN_INVALID_ADDRESS);
}
- last_timestamp = map->timestamp;
- entry = first_entry;
+ rv = KERN_SUCCESS;
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 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 (flags & VM_MAP_WIRE_HOLESOK)
- 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;
- goto done;
- }
- }
- if (entry == first_entry)
- first_entry = tmp_entry;
- else
- first_entry = NULL;
- entry = tmp_entry;
- }
- last_timestamp = map->timestamp;
- continue;
- }
vm_map_clip_start(map, entry, start);
vm_map_clip_end(map, entry, end);
/*
@@ -2930,11 +2939,11 @@
* Check the map for holes in the specified region.
* If VM_MAP_WIRE_HOLESOK was specified, skip this check.
*/
- if (((flags & VM_MAP_WIRE_HOLESOK) == 0) &&
+ if ((!holes_ok) &&
(entry->end < end && entry->next->start > entry->end)) {
end = entry->end;
rv = KERN_INVALID_ADDRESS;
- goto done;
+ break;
}
/*
* If system unwiring, require that the entry is system wired.
@@ -2943,19 +2952,22 @@
vm_map_entry_system_wired_count(entry) == 0) {
end = entry->end;
rv = KERN_INVALID_ARGUMENT;
- goto done;
+ break;
}
- entry = entry->next;
+ entry = vm_map_get_avail_entry(map, start, &end, holes_ok,
+ entry->next, &first_entry);
+ if (entry == NULL) {
+ rv = KERN_INVALID_ADDRESS;
+ break;
+ }
}
- rv = KERN_SUCCESS;
-done:
- need_wakeup = FALSE;
+ need_wakeup = false;
if (first_entry == NULL) {
result = vm_map_lookup_entry(map, start, &first_entry);
- if (!result && (flags & VM_MAP_WIRE_HOLESOK))
+ if (!result) {
+ KASSERT(holes_ok, ("vm_map_unwire: lookup failed"));
first_entry = first_entry->next;
- else
- KASSERT(result, ("vm_map_unwire: lookup failed"));
+ }
}
for (entry = first_entry; entry->start < end; entry = entry->next) {
/*
@@ -2969,7 +2981,7 @@
*/
if ((entry->eflags & MAP_ENTRY_IN_TRANSITION) == 0 ||
entry->wiring_thread != curthread) {
- KASSERT((flags & VM_MAP_WIRE_HOLESOK) != 0,
+ KASSERT(holes_ok,
("vm_map_unwire: !HOLESOK and new/changed entry"));
continue;
}
@@ -2991,7 +3003,7 @@
entry->wiring_thread = NULL;
if (entry->eflags & MAP_ENTRY_NEEDS_WAKEUP) {
entry->eflags &= ~MAP_ENTRY_NEEDS_WAKEUP;
- need_wakeup = TRUE;
+ need_wakeup = true;
}
vm_map_simplify_entry(map, entry);
}
@@ -3085,7 +3097,8 @@
u_long npages;
u_int last_timestamp;
int rv;
- boolean_t need_wakeup, result, user_wire;
+ boolean_t result;
+ bool holes_ok, need_wakeup, user_wire;
vm_prot_t prot;
VM_MAP_ASSERT_LOCKED(map);
@@ -3095,62 +3108,16 @@
prot = 0;
if (flags & VM_MAP_WIRE_WRITE)
prot |= VM_PROT_WRITE;
- user_wire = (flags & VM_MAP_WIRE_USER) ? TRUE : FALSE;
+ user_wire = (flags & VM_MAP_WIRE_USER) != 0;
+ holes_ok = (flags & VM_MAP_WIRE_HOLESOK) != 0;
VM_MAP_RANGE_CHECK(map, start, end);
- if (!vm_map_lookup_entry(map, start, &first_entry)) {
- if (flags & VM_MAP_WIRE_HOLESOK)
- first_entry = first_entry->next;
- else
- return (KERN_INVALID_ADDRESS);
- }
+ entry = vm_map_get_avail_entry(map, start, &end, holes_ok,
+ NULL, &first_entry);
+ if (entry == NULL)
+ return (KERN_INVALID_ADDRESS);
+ rv = KERN_SUCCESS;
last_timestamp = map->timestamp;
- 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?
- */
- }
- 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 (flags & VM_MAP_WIRE_HOLESOK)
- 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;
- continue;
- }
vm_map_clip_start(map, entry, start);
vm_map_clip_end(map, entry, end);
/*
@@ -3165,14 +3132,12 @@
if ((entry->protection & (VM_PROT_READ | VM_PROT_EXECUTE)) == 0
|| (entry->protection & prot) != prot) {
entry->eflags |= MAP_ENTRY_WIRE_SKIPPED;
- if ((flags & VM_MAP_WIRE_HOLESOK) == 0) {
+ if (!holes_ok) {
end = entry->end;
rv = KERN_INVALID_ADDRESS;
- goto done;
+ break;
}
- goto next_entry;
- }
- if (entry->wired_count == 0) {
+ } else if (entry->wired_count == 0) {
entry->wired_count++;
npages = atop(entry->end - entry->start);
@@ -3181,7 +3146,7 @@
entry->start);
end = entry->end;
rv = KERN_RESOURCE_SHORTAGE;
- goto done;
+ break;
}
/*
@@ -3240,7 +3205,7 @@
if (user_wire)
vm_map_wire_user_count_sub(npages);
end = entry->end;
- goto done;
+ break;
}
} else if (!user_wire ||
(entry->eflags & MAP_ENTRY_USER_WIRED) == 0) {
@@ -3250,24 +3215,27 @@
* Check the map for holes in the specified region.
* If VM_MAP_WIRE_HOLESOK was specified, skip this check.
*/
- next_entry:
- if ((flags & VM_MAP_WIRE_HOLESOK) == 0 &&
+ if (!holes_ok &&
entry->end < end && entry->next->start > entry->end) {
end = entry->end;
rv = KERN_INVALID_ADDRESS;
- goto done;
+ break;
}
- entry = entry->next;
+ entry = vm_map_get_avail_entry(map, start, &end, holes_ok,
+ entry->next, &first_entry);
+ if (entry == NULL) {
+ rv = KERN_INVALID_ADDRESS;
+ break;
+ }
+ last_timestamp = map->timestamp;
}
- rv = KERN_SUCCESS;
-done:
- need_wakeup = FALSE;
+ need_wakeup = false;
if (first_entry == NULL) {
result = vm_map_lookup_entry(map, start, &first_entry);
- if (!result && (flags & VM_MAP_WIRE_HOLESOK))
+ if (!result) {
+ KASSERT(holes_ok, ("vm_map_wire: lookup failed"));
first_entry = first_entry->next;
- else
- KASSERT(result, ("vm_map_wire: lookup failed"));
+ }
}
for (entry = first_entry; entry->start < end; entry = entry->next) {
/*
@@ -3281,15 +3249,14 @@
*/
if ((entry->eflags & MAP_ENTRY_IN_TRANSITION) == 0 ||
entry->wiring_thread != curthread) {
- KASSERT((flags & VM_MAP_WIRE_HOLESOK) != 0,
+ KASSERT(holes_ok,
("vm_map_wire: !HOLESOK and new/changed entry"));
continue;
}
- if ((entry->eflags & MAP_ENTRY_WIRE_SKIPPED) != 0)
- goto next_entry_done;
-
- if (rv == KERN_SUCCESS) {
+ if ((entry->eflags & MAP_ENTRY_WIRE_SKIPPED) != 0) {
+ /* do nothing */
+ } else if (rv == KERN_SUCCESS) {
if (user_wire)
entry->eflags |= MAP_ENTRY_USER_WIRED;
} else if (entry->wired_count == -1) {
@@ -3312,7 +3279,6 @@
} else
entry->wired_count--;
}
- next_entry_done:
KASSERT((entry->eflags & MAP_ENTRY_IN_TRANSITION) != 0,
("vm_map_wire: in-transition flag missing %p", entry));
KASSERT(entry->wiring_thread == curthread,
@@ -3322,7 +3288,7 @@
entry->wiring_thread = NULL;
if (entry->eflags & MAP_ENTRY_NEEDS_WAKEUP) {
entry->eflags &= ~MAP_ENTRY_NEEDS_WAKEUP;
- need_wakeup = TRUE;
+ need_wakeup = true;
}
vm_map_simplify_entry(map, entry);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 10, 12:32 AM (9 h, 33 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17077857
Default Alt Text
D20833.id59316.diff (10 KB)
Attached To
Mode
D20833: factor out common wiring code
Attached
Detach File
Event Timeline
Log In to Comment