Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/uvm - Rework uvm_anfree() into uvm_anon_freelst(), which...



details:   https://anonhg.NetBSD.org/src/rev/874bf0d38dd5
branches:  trunk
changeset: 768025:874bf0d38dd5
user:      rmind <rmind%NetBSD.org@localhost>
date:      Sat Aug 06 17:25:03 2011 +0000

description:
- Rework uvm_anfree() into uvm_anon_freelst(), which always drops the lock.
- Free anons in uvm_anon_freelst() without lock held.
- Mechanic sync to unused loaning code.

diffstat:

 sys/uvm/uvm_amap.c  |  47 ++++++++++++++++----------------
 sys/uvm/uvm_anon.c  |  75 +++++++++++++++++++++++++++++++++++-----------------
 sys/uvm/uvm_anon.h  |   5 ++-
 sys/uvm/uvm_fault.c |   6 ++--
 sys/uvm/uvm_loan.c  |  37 ++++++++++++--------------
 sys/uvm/uvm_map.c   |  12 ++++----
 6 files changed, 102 insertions(+), 80 deletions(-)

diffs (truncated from 528 to 300 lines):

diff -r 29624e0ca717 -r 874bf0d38dd5 sys/uvm/uvm_amap.c
--- a/sys/uvm/uvm_amap.c        Sat Aug 06 17:17:39 2011 +0000
+++ b/sys/uvm/uvm_amap.c        Sat Aug 06 17:25:03 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_amap.c,v 1.101 2011/07/05 13:47:24 yamt Exp $      */
+/*     $NetBSD: uvm_amap.c,v 1.102 2011/08/06 17:25:03 rmind Exp $     */
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.101 2011/07/05 13:47:24 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.102 2011/08/06 17:25:03 rmind Exp $");
 
 #include "opt_uvmhist.h"
 
@@ -365,9 +365,8 @@
                                amap_pp_adjref(amap, slotoff + slotmapped,
                                    slotadd, 1, &tofree);
                        }
-                       uvm_anfree(tofree);
 #endif
-                       amap_unlock(amap);
+                       uvm_anon_freelst(amap, tofree);
                        UVMHIST_LOG(maphist,
                            "<- done (case 1f), amap = 0x%x, sltneed=%d",
                            amap, slotneed, 0, 0);
@@ -382,9 +381,8 @@
                                amap_pp_adjref(amap, slotoff, slotadd, 1,
                                    &tofree);
                        }
-                       uvm_anfree(tofree);
 #endif
-                       amap_unlock(amap);
+                       uvm_anon_freelst(amap, tofree);
                        UVMHIST_LOG(maphist,
                            "<- done (case 1b), amap = 0x%x, sltneed=%d",
                            amap, slotneed, 0, 0);
@@ -412,8 +410,7 @@
                        }
 #endif
                        amap->am_nslot = slotneed;
-                       uvm_anfree(tofree);
-                       amap_unlock(amap);
+                       uvm_anon_freelst(amap, tofree);
 
                        /*
                         * no need to zero am_anon since that was done at
@@ -614,8 +611,8 @@
        oldnslots = amap->am_maxslot;
        amap->am_maxslot = slotalloc;
 
-       uvm_anfree(tofree);
-       amap_unlock(amap);
+       uvm_anon_freelst(amap, tofree);
+
        kmem_free(oldsl, oldnslots * sizeof(*oldsl));
        kmem_free(oldbck, oldnslots * sizeof(*oldbck));
        kmem_free(oldover, oldnslots * sizeof(*oldover));
@@ -694,6 +691,7 @@
 void
 amap_wipeout(struct vm_amap *amap)
 {
+       struct vm_anon *tofree = NULL;
        u_int lcv;
 
        UVMHIST_FUNC("amap_wipeout"); UVMHIST_CALLED(maphist);
@@ -724,11 +722,12 @@
                    anon->an_ref, 0, 0);
 
                /*
-                * Drop the reference, and free the anon, if it is last.
+                * Drop the reference.  Defer freeing.
                 */
 
                if (--anon->an_ref == 0) {
-                       uvm_anfree(anon);
+                       anon->an_link = tofree;
+                       tofree = anon;
                }
                if (curlwp->l_cpu->ci_schedstate.spc_flags & SPCF_SHOULDYIELD) {
                        preempt();
@@ -740,7 +739,7 @@
         */
 
        amap->am_nused = 0;
-       amap_unlock(amap);
+       uvm_anon_freelst(amap, tofree);
        amap_free(amap);
        UVMHIST_LOG(maphist,"<- done!", 0,0,0,0);
 }
@@ -915,7 +914,6 @@
                    len >> PAGE_SHIFT, -1, &tofree);
        }
 #endif
-       uvm_anfree(tofree);
 
        /*
         * If we referenced any anons, then share the source amap's lock.
@@ -927,9 +925,11 @@
                amap->am_lock = srcamap->am_lock;
                mutex_obj_hold(amap->am_lock);
        }
-       amap_unlock(srcamap);
-       if (amap->am_lock == NULL)
+       uvm_anon_freelst(srcamap, tofree);
+
+       if (amap->am_lock == NULL) {
                amap->am_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
+       }
        amap_list_insert(amap);
 
        /*
@@ -1047,9 +1047,10 @@
                        if (nanon) {
                                nanon->an_ref--;
                                KASSERT(nanon->an_ref == 0);
-                               uvm_anfree(nanon);
+                               uvm_anon_freelst(amap, nanon);
+                       } else {
+                               amap_unlock(amap);
                        }
-                       amap_unlock(amap);
                        uvm_wait("cownowpage");
                        goto ReStart;
                }
@@ -1279,7 +1280,7 @@
                if (--anon->an_ref == 0) {
                        /*
                         * Eliminated the last reference to an anon - defer
-                        * freeing as uvm_anfree() can unlock the amap.
+                        * freeing as uvm_anon_freelst() will unlock the amap.
                         */
                        anon->an_link = *tofree;
                        *tofree = anon;
@@ -1543,6 +1544,8 @@
 amap_adjref_anons(struct vm_amap *amap, vaddr_t offset, vsize_t len,
     int refv, bool all)
 {
+       struct vm_anon *tofree = NULL;
+
 #ifdef UVM_AMAP_PPREF
        KASSERT(mutex_owned(amap->am_lock));
 
@@ -1550,16 +1553,14 @@
                amap_pp_establish(amap, offset);
        }
        if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
-               struct vm_anon *tofree = NULL;
-
                if (all) {
                        amap_pp_adjref(amap, 0, amap->am_nslot, refv, &tofree);
                } else {
                        amap_pp_adjref(amap, offset, len, refv, &tofree);
                }
-               uvm_anfree(tofree);
        }
 #endif
+       uvm_anon_freelst(amap, tofree);
 }
 
 /*
@@ -1580,7 +1581,6 @@
        }
        amap->am_ref++;
        amap_adjref_anons(amap, offset, len, 1, (flags & AMAP_REFALL) != 0);
-       amap_unlock(amap);
 
        UVMHIST_LOG(maphist,"<- done!  amap=0x%x", amap, 0, 0, 0);
 }
@@ -1620,7 +1620,6 @@
                amap->am_flags &= ~AMAP_SHARED;
        }
        amap_adjref_anons(amap, offset, len, -1, all);
-       amap_unlock(amap);
 
        UVMHIST_LOG(maphist,"<- done!", 0, 0, 0, 0);
 }
diff -r 29624e0ca717 -r 874bf0d38dd5 sys/uvm/uvm_anon.c
--- a/sys/uvm/uvm_anon.c        Sat Aug 06 17:17:39 2011 +0000
+++ b/sys/uvm/uvm_anon.c        Sat Aug 06 17:25:03 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_anon.c,v 1.58 2011/07/05 13:47:24 yamt Exp $       */
+/*     $NetBSD: uvm_anon.c,v 1.59 2011/08/06 17:25:03 rmind 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.58 2011/07/05 13:47:24 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_anon.c,v 1.59 2011/08/06 17:25:03 rmind Exp $");
 
 #include "opt_uvmhist.h"
 
@@ -62,6 +62,7 @@
        struct vm_anon *anon = object;
 
        anon->an_ref = 0;
+       anon->an_lock = NULL;
        anon->an_page = NULL;
 #if defined(VMSWAP)
        anon->an_swslot = 0;
@@ -82,33 +83,32 @@
        anon = pool_cache_get(&uvm_anon_cache, PR_NOWAIT);
        if (anon) {
                KASSERT(anon->an_ref == 0);
+               KASSERT(anon->an_lock == NULL);
                KASSERT(anon->an_page == NULL);
 #if defined(VMSWAP)
                KASSERT(anon->an_swslot == 0);
 #endif
                anon->an_ref = 1;
-               anon->an_lock = NULL;
        }
        return anon;
 }
 
 /*
- * uvm_anfree1: free a single anon.
+ * uvm_anon_dispose: free any resident page or swap resources of anon.
  *
  * => anon must be removed from the amap (if anon was in an amap).
- * => amap must be locked or anon must not be associated.
- * => amap lock may be dropped and re-acquired here.
+ * => amap must be locked; we may drop and re-acquire the lock here.
  */
 
 static void
-uvm_anfree1(struct vm_anon *anon)
+uvm_anon_dispose(struct vm_anon *anon)
 {
        struct vm_page *pg = anon->an_page;
 
-       UVMHIST_FUNC("uvm_anfree"); UVMHIST_CALLED(maphist);
+       UVMHIST_FUNC("uvm_anon_dispose"); UVMHIST_CALLED(maphist);
        UVMHIST_LOG(maphist,"(anon=0x%x)", anon, 0,0,0);
 
-       KASSERT(anon->an_lock == NULL || mutex_owned(anon->an_lock));
+       KASSERT(mutex_owned(anon->an_lock));
 
        /*
         * If there is a resident page and it is loaned, then anon may not
@@ -180,35 +180,57 @@
 #endif
 
        /*
-        * Free any swap resources, leave a page replacement hint, drop
-        * the reference on lock and finally destroy the anon itself.
+        * Free any swap resources, leave a page replacement hint.
         */
 
        uvm_anon_dropswap(anon);
        uvmpdpol_anfree(anon);
+       UVMHIST_LOG(maphist,"<- done!",0,0,0,0);
+}
 
+/*
+ * uvm_anon_free: free a single anon.
+ *
+ * => anon must be already disposed.
+ */
+void
+uvm_anon_free(struct vm_anon *anon)
+{
+
+       KASSERT(anon->an_ref == 0);
+       KASSERT(anon->an_lock == NULL);
        KASSERT(anon->an_page == NULL);
 #if defined(VMSWAP)
        KASSERT(anon->an_swslot == 0);
 #endif
-
        pool_cache_put(&uvm_anon_cache, anon);
-       UVMHIST_LOG(maphist,"<- done!",0,0,0,0);
 }
 
 /*
- * uvm_anfree: free a linked list of anon structures.
+ * uvm_anon_freelst: free a linked list of anon structures.
+ *
+ * => anon must be locked, we will unlock it.
  */
 void
-uvm_anfree(struct vm_anon *anon)
+uvm_anon_freelst(struct vm_amap *amap, struct vm_anon *anonlst)
 {
-       struct vm_anon *next;
+       struct vm_anon *anon = anonlst;
+
+       KASSERT(mutex_owned(amap->am_lock));
 
-       for (; anon != NULL; anon = next) {
-               /* Note: clearing an_link also clears a reference count. */
-               next = anon->an_link;
-               anon->an_link = NULL;
-               uvm_anfree1(anon);



Home | Main Index | Thread Index | Old Index