]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/vm/vm_pageout.c
xnu-517.3.15.tar.gz
[apple/xnu.git] / osfmk / vm / vm_pageout.c
index 19a6eb88519c66ec76cf5a343399e0cc69f737fc..82c4ba67898da20e6d0889ad71c305d28521b27b 100644 (file)
@@ -1119,9 +1119,32 @@ void
 vm_pageout_throttle(
        register vm_page_t m)
 {
+        register vm_object_t object;
+
+       /*
+        * need to keep track of the object we 
+        * started with... if we drop the object lock
+        * due to the throttle, it's possible that someone
+        * else will gather this page into an I/O if this
+        * is an external object... the page will then be
+        * potentially freed before we unwedge from the
+        * throttle... this is ok since no one plays with
+        * the page directly after the throttle... the object
+        * and offset are passed into the memory_object_data_return
+        * function where eventually it's relooked up against the
+        * object... if it's changed state or there is no longer
+        * a page at that offset, the pageout just finishes without
+        * issuing an I/O
+        */
+       object = m->object;
+
        assert(!m->laundry);
        m->laundry = TRUE;
-       while (vm_page_laundry_count >= vm_page_laundry_max) {
+       if (!object->internal)
+               vm_page_burst_count++;
+       vm_page_laundry_count++;
+
+       while (vm_page_laundry_count > vm_page_laundry_max) {
                /*
                 * Set the threshold for when vm_page_free()
                 * should wake us up.
@@ -1130,18 +1153,15 @@ vm_pageout_throttle(
 
                assert_wait((event_t) &vm_page_laundry_count, THREAD_UNINT);
                vm_page_unlock_queues();
-               vm_object_unlock(m->object);
+               vm_object_unlock(object);
                /*
                 * Pause to let the default pager catch up.
                 */
                thread_block((void (*)(void)) 0);
 
-               vm_object_lock(m->object);
+               vm_object_lock(object);
                vm_page_lock_queues();
        }
-       if (!m->object->internal)
-               vm_page_burst_count++;
-       vm_page_laundry_count++;
 }
 
 /*