Module Name: src Committed By: ad Date: Sun Dec 1 17:02:50 UTC 2019
Modified Files: src/sys/uvm: uvm_anon.c Log Message: Free pages in batch instead of taking uvm_pageqlock for each one. To generate a diff of this commit: cvs rdiff -u -r1.65 -r1.66 src/sys/uvm/uvm_anon.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/uvm/uvm_anon.c diff -u src/sys/uvm/uvm_anon.c:1.65 src/sys/uvm/uvm_anon.c:1.66 --- src/sys/uvm/uvm_anon.c:1.65 Sun Dec 1 14:40:31 2019 +++ src/sys/uvm/uvm_anon.c Sun Dec 1 17:02:50 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_anon.c,v 1.65 2019/12/01 14:40:31 ad Exp $ */ +/* $NetBSD: uvm_anon.c,v 1.66 2019/12/01 17:02:50 ad Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_anon.c,v 1.65 2019/12/01 14:40:31 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_anon.c,v 1.66 2019/12/01 17:02:50 ad Exp $"); #include "opt_uvmhist.h" @@ -94,7 +94,7 @@ uvm_analloc(void) } /* - * uvm_anon_dispose: free any resident page or swap resources of anon. + * uvm_anon_dispose: break loans and remove pmap mapping * * => anon must be removed from the amap (if anon was in an amap). * => amap must be locked; we may drop and re-acquire the lock here. @@ -110,17 +110,6 @@ uvm_anon_dispose(struct vm_anon *anon) KASSERT(mutex_owned(anon->an_lock)); /* - * If there is a resident page and it is loaned, then anon may not - * own it. Call out to uvm_anon_lockloanpg() to identify and lock - * the real owner of the page. - */ - - if (pg && pg->loan_count) { - KASSERT(anon->an_lock != NULL); - pg = uvm_anon_lockloanpg(anon); - } - - /* * Dispose the page, if it is resident. */ @@ -128,6 +117,16 @@ uvm_anon_dispose(struct vm_anon *anon) KASSERT(anon->an_lock != NULL); /* + * If there is a resident page and it is loaned, then anon + * may not own it. Call out to uvm_anon_lockloanpg() to + * identify and lock the real owner of the page. + */ + + if (pg->loan_count) { + pg = uvm_anon_lockloanpg(anon); + } + + /* * If the page is owned by a UVM object (now locked), * then kill the loan on the page rather than free it, * and release the object lock. @@ -160,12 +159,6 @@ uvm_anon_dispose(struct vm_anon *anon) mutex_obj_hold(anon->an_lock); return false; } - mutex_enter(&uvm_pageqlock); - uvm_pagefree(pg); - mutex_exit(&uvm_pageqlock); - UVMHIST_LOG(maphist, "anon 0x%#jx, page 0x%#jx: " - "freed now!", (uintptr_t)anon, (uintptr_t)pg, - 0, 0); } } @@ -177,12 +170,6 @@ uvm_anon_dispose(struct vm_anon *anon) } #endif - /* - * Free any swap resources, leave a page replacement hint. - */ - - uvm_anon_dropswap(anon); - uvmpdpol_anfree(anon); UVMHIST_LOG(maphist,"<- done!",0,0,0,0); return true; } @@ -196,6 +183,10 @@ void uvm_anon_free(struct vm_anon *anon) { +#if defined(VMSWAP) + /* Free any dangling swap slot. */ + uvm_anon_dropswap(anon); +#endif KASSERT(anon->an_ref == 0); KASSERT(anon->an_lock == NULL); KASSERT(anon->an_page == NULL); @@ -208,15 +199,23 @@ uvm_anon_free(struct vm_anon *anon) /* * uvm_anon_freelst: free a linked list of anon structures. * - * => anon must be locked, we will unlock it. + * => amap must be locked, we will unlock it. */ void uvm_anon_freelst(struct vm_amap *amap, struct vm_anon *anonlst) { struct vm_anon *anon; struct vm_anon **anonp = &anonlst; + struct vm_page *pg; KASSERT(mutex_owned(amap->am_lock)); + + if (anonlst == NULL) { + amap_unlock(amap); + return; + } + + /* Break loans and hardware mappings. Defer release of busy pages. */ while ((anon = *anonp) != NULL) { if (!uvm_anon_dispose(anon)) { /* Do not free this anon. */ @@ -227,8 +226,22 @@ uvm_anon_freelst(struct vm_amap *amap, s anonp = &anon->an_link; } } + + /* Free pages and leave a page replacement hint. */ + mutex_enter(&uvm_pageqlock); + for (anon = anonlst; anon != NULL; anon = anon->an_link) { + UVMHIST_LOG(maphist, "anon 0x%#jx, page 0x%#jx: " + "releasing now!", (uintptr_t)anon, + (uintptr_t)anon->an_page, 0, 0); + if ((pg = anon->an_page) != NULL) { + uvm_pagefree(pg); + } + uvmpdpol_anfree(anon); + } + mutex_exit(&uvm_pageqlock); amap_unlock(amap); + /* Free swap space, pages and vm_anon. */ while (anonlst) { anon = anonlst->an_link; /* Note: clears an_ref as well. */