Source-Changes-HG archive

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

[src/netbsd-3]: src/sys/uvm Pullup via patch (requested in ticket #939 by chs)



details:   https://anonhg.NetBSD.org/src/rev/8cce86685366
branches:  netbsd-3
changeset: 577459:8cce86685366
user:      jmc <jmc%NetBSD.org@localhost>
date:      Mon Nov 07 17:33:17 2005 +0000

description:
Pullup via patch (requested in ticket #939 by chs)

  In amap_cow_now(), handle the case where we have to sleep and some of the
  already-copied pages are paged out.  anons that have already been copied
  will have refcount == 1, whereas anons that still need to be copied will
  have refcount > 1. PR#25392, PR#30257, PR#31924

diffstat:

 sys/uvm/uvm_amap.c |  151 ++++++++++++++++++++++++++++------------------------
 1 files changed, 80 insertions(+), 71 deletions(-)

diffs (194 lines):

diff -r 8467f020895a -r 8cce86685366 sys/uvm/uvm_amap.c
--- a/sys/uvm/uvm_amap.c        Sun Nov 06 17:54:01 2005 +0000
+++ b/sys/uvm/uvm_amap.c        Mon Nov 07 17:33:17 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_amap.c,v 1.57 2005/01/30 17:23:05 chs Exp $        */
+/*     $NetBSD: uvm_amap.c,v 1.57.4.1 2005/11/07 17:33:17 jmc Exp $    */
 
 /*
  *
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.57 2005/01/30 17:23:05 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.57.4.1 2005/11/07 17:33:17 jmc Exp $");
 
 #undef UVM_AMAP_INLINE         /* enable/disable amap inlines */
 
@@ -905,7 +905,6 @@
 
 ReStart:
        amap_lock(amap);
-
        for (lcv = 0 ; lcv < amap->am_nused ; lcv++) {
 
                /*
@@ -915,89 +914,99 @@
                slot = amap->am_slots[lcv];
                anon = amap->am_anon[slot];
                simple_lock(&anon->an_lock);
-               pg = anon->u.an_page;
 
                /*
-                * page must be resident since parent is wired
+                * If the anon has only one ref, we must have already copied it.
+                * This can happen if we needed to sleep waiting for memory
+                * in a previous run through this loop.  The new page might
+                * even have been paged out, since the new page is not wired.
                 */
 
-               if (pg == NULL)
-                   panic("amap_cow_now: non-resident wired page in anon %p",
-                       anon);
+               if (anon->an_ref == 1) {
+                       KASSERT(anon->u.an_page != NULL ||
+                               anon->an_swslot != 0);
+                       simple_unlock(&anon->an_lock);
+                       continue;
+               }
+
+               /*
+                * The old page must be resident since the parent is wired.
+                */
+
+               pg = anon->u.an_page;
+               KASSERT(pg != NULL);
+               KASSERT(pg->wire_count > 0);
 
                /*
-                * if the anon ref count is one and the page is not loaned,
-                * then we are safe (the child has exclusive access to the
-                * page).  if the page is loaned, then it must already be
-                * mapped read-only.
-                *
-                * we only need to get involved when these are not true.
-                * [note: if loan_count == 0, then the anon must own the page]
+                * If the page is loaned then it must already be mapped
+                * read-only and we don't need to copy it.
+                */
+
+               if (pg->loan_count != 0) {
+                       simple_unlock(&anon->an_lock);
+                       continue;
+               }
+               KASSERT(pg->uanon == anon && pg->uobject == NULL);
+
+               /*
+                * if the page is busy then we have to unlock, wait for
+                * it and then restart.
                 */
 
-               if (anon->an_ref > 1 && pg->loan_count == 0) {
+               if (pg->flags & PG_BUSY) {
+                       pg->flags |= PG_WANTED;
+                       amap_unlock(amap);
+                       UVM_UNLOCK_AND_WAIT(pg, &anon->an_lock, FALSE,
+                           "cownow", 0);
+                       goto ReStart;
+               }
 
-                       /*
-                        * if the page is busy then we have to unlock, wait for
-                        * it and then restart.
-                        */
-                       if (pg->flags & PG_BUSY) {
-                               pg->flags |= PG_WANTED;
-                               amap_unlock(amap);
-                               UVM_UNLOCK_AND_WAIT(pg, &anon->an_lock, FALSE,
-                                   "cownow", 0);
-                               goto ReStart;
-                       }
+               /*
+                * ok, time to do a copy-on-write to a new anon
+                */
+
+               nanon = uvm_analloc();
+               if (nanon) {
+                       npg = uvm_pagealloc(NULL, 0, nanon, 0);
+               } else
+                       npg = NULL;     /* XXX: quiet gcc warning */
+               if (nanon == NULL || npg == NULL) {
 
                        /*
-                        * ok, time to do a copy-on-write to a new anon
-                        */
-                       nanon = uvm_analloc();
-                       if (nanon) {
-                               /* nanon is locked! */
-                               npg = uvm_pagealloc(NULL, 0, nanon, 0);
-                       } else
-                               npg = NULL;     /* XXX: quiet gcc warning */
-
-                       if (nanon == NULL || npg == NULL) {
-                               /* out of memory */
-                               /*
-                                * XXXCDC: we should cause fork to fail, but
-                                * we can't ...
-                                */
-                               if (nanon) {
-                                       nanon->an_ref--;
-                                       simple_unlock(&nanon->an_lock);
-                                       uvm_anfree(nanon);
-                               }
-                               simple_unlock(&anon->an_lock);
-                               amap_unlock(amap);
-                               uvm_wait("cownowpage");
-                               goto ReStart;
-                       }
-
-                       /*
-                        * got it... now we can copy the data and replace anon
-                        * with our new one...
+                        * XXXCDC: we should cause fork to fail, but we can't.
                         */
 
-                       uvm_pagecopy(pg, npg);          /* old -> new */
-                       anon->an_ref--;                 /* can't drop to zero */
-                       amap->am_anon[slot] = nanon;    /* replace */
+                       if (nanon) {
+                               nanon->an_ref--;
+                               simple_unlock(&nanon->an_lock);
+                               uvm_anfree(nanon);
+                       }
+                       simple_unlock(&anon->an_lock);
+                       amap_unlock(amap);
+                       uvm_wait("cownowpage");
+                       goto ReStart;
+               }
+
+               /*
+                * got it... now we can copy the data and replace anon
+                * with our new one...
+                */
 
-                       /*
-                        * drop PG_BUSY on new page ... since we have had it's
-                        * owner locked the whole time it can't be
-                        * PG_RELEASED | PG_WANTED.
-                        */
+               uvm_pagecopy(pg, npg);          /* old -> new */
+               anon->an_ref--;                 /* can't drop to zero */
+               amap->am_anon[slot] = nanon;    /* replace */
 
-                       uvm_lock_pageq();
-                       uvm_pageactivate(npg);
-                       uvm_unlock_pageq();
-                       npg->flags &= ~(PG_BUSY|PG_FAKE);
-                       UVM_PAGE_OWN(npg, NULL);
-                       simple_unlock(&nanon->an_lock);
-               }
+               /*
+                * drop PG_BUSY on new page ... since we have had its owner
+                * locked the whole time it can't be PG_RELEASED or PG_WANTED.
+                */
+
+               uvm_lock_pageq();
+               uvm_pageactivate(npg);
+               uvm_unlock_pageq();
+               npg->flags &= ~(PG_BUSY|PG_FAKE);
+               UVM_PAGE_OWN(npg, NULL);
+               simple_unlock(&nanon->an_lock);
                simple_unlock(&anon->an_lock);
        }
        amap_unlock(amap);



Home | Main Index | Thread Index | Old Index