Author: alc
Date: Sat Nov 20 22:30:09 2010
New Revision: 215597
URL: http://svn.freebsd.org/changeset/base/215597

Log:
  Optimize vm_object_terminate().
  
  Reviewed by:  kib
  MFC after:    1 week

Modified:
  head/sys/vm/vm_object.c

Modified: head/sys/vm/vm_object.c
==============================================================================
--- head/sys/vm/vm_object.c     Sat Nov 20 21:44:18 2010        (r215596)
+++ head/sys/vm/vm_object.c     Sat Nov 20 22:30:09 2010        (r215597)
@@ -661,7 +661,7 @@ vm_object_destroy(vm_object_t object)
 void
 vm_object_terminate(vm_object_t object)
 {
-       vm_page_t p;
+       vm_page_t p, p_next;
 
        VM_OBJECT_LOCK_ASSERT(object, MA_OWNED);
 
@@ -701,22 +701,41 @@ vm_object_terminate(vm_object_t object)
                object->ref_count));
 
        /*
-        * Now free any remaining pages. For internal objects, this also
-        * removes them from paging queues. Don't free wired pages, just
-        * remove them from the object. 
+        * Free any remaining pageable pages.  This also removes them from the
+        * paging queues.  However, don't free wired pages, just remove them
+        * from the object.  Rather than incrementally removing each page from
+        * the object, the page and object are reset to any empty state. 
         */
-       while ((p = TAILQ_FIRST(&object->memq)) != NULL) {
+       TAILQ_FOREACH_SAFE(p, &object->memq, listq, p_next) {
                KASSERT(!p->busy && (p->oflags & VPO_BUSY) == 0,
-                       ("vm_object_terminate: freeing busy page %p "
-                       "p->busy = %d, p->oflags %x\n", p, p->busy, p->oflags));
+                   ("vm_object_terminate: freeing busy page %p", p));
                vm_page_lock(p);
+               /*
+                * Optimize the page's removal from the object by resetting
+                * its "object" field.  Specifically, if the page is not
+                * wired, then the effect of this assignment is that
+                * vm_page_free()'s call to vm_page_remove() will return
+                * immediately without modifying the page or the object.
+                */ 
+               p->object = NULL;
                if (p->wire_count == 0) {
                        vm_page_free(p);
                        PCPU_INC(cnt.v_pfree);
-               } else
-                       vm_page_remove(p);
+               }
                vm_page_unlock(p);
        }
+       /*
+        * If the object contained any pages, then reset it to an empty state.
+        * None of the object's fields, including "resident_page_count", were
+        * modified by the preceding loop.
+        */
+       if (object->resident_page_count != 0) {
+               object->root = NULL;
+               TAILQ_INIT(&object->memq);
+               object->resident_page_count = 0;
+               if (object->type == OBJT_VNODE)
+                       vdrop(object->handle);
+       }
 
 #if VM_NRESERVLEVEL > 0
        if (__predict_false(!LIST_EMPTY(&object->rvq)))
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to