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)
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to