diff options
author | alc <alc@FreeBSD.org> | 2010-11-20 22:30:09 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2010-11-20 22:30:09 +0000 |
commit | 5bd8badd5ec0af1082cbc5e11e674721bbfab61f (patch) | |
tree | fe4fe4be2a70ebeb8f74fc966fb59894f4f88cee | |
parent | c2d4047d05b775388f114756ed4889c6d6e6e3d5 (diff) | |
download | FreeBSD-src-5bd8badd5ec0af1082cbc5e11e674721bbfab61f.zip FreeBSD-src-5bd8badd5ec0af1082cbc5e11e674721bbfab61f.tar.gz |
Optimize vm_object_terminate().
Reviewed by: kib
MFC after: 1 week
-rw-r--r-- | sys/vm/vm_object.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 48dd3b6..b7f47b5 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -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))) |