Source-Changes-HG archive

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

[src/trunk]: src/sys/uvm Implement backwards extension of amaps. There are t...



details:   https://anonhg.NetBSD.org/src/rev/e4cc2fb0269d
branches:  trunk
changeset: 539317:e4cc2fb0269d
user:      atatat <atatat%NetBSD.org@localhost>
date:      Thu Nov 14 17:58:48 2002 +0000

description:
Implement backwards extension of amaps.  There are three cases to deal
with:

Case #1 -- adjust offset: The slot offset in the aref can be
decremented to cover the required size addition.

Case #2 -- move pages and adjust offset: The slot offset is not large
enough, but the amap contains enough inactive space *after* the mapped
pages to make up the difference, so active slots are slid to the "end"
of the amap, and the slot offset is, again, adjusted to cover the
required size addition.  This optimizes for hitting case #1 again on
the next small extension.

Case #3 -- reallocate, move pages, and adjust offset: There is not
enough inactive space in the amap, so the arrays are reallocated, and
the active pages are copied again to the "end" of the amap, and the
slot offset is adjusted to cover the required size.  This also
optimizes for hitting case #1 on the next backwards extension.

This provides the missing piece in the "forward extension of
vm_map_entries" logic, so the merge failure counters have been
removed.

Not many applications will make any use of this at this time (except
for jvms and perhaps gcc3), but a "top-down" memory allocator will use
it extensively.

diffstat:

 sys/uvm/uvm_amap.c |  216 ++++++++++++++++++++++++++++++++++++++++++----------
 sys/uvm/uvm_amap.h |   10 +-
 sys/uvm/uvm_map.c  |   89 +++++++++++++--------
 3 files changed, 239 insertions(+), 76 deletions(-)

diffs (truncated from 514 to 300 lines):

diff -r 6fcd03f75c6e -r e4cc2fb0269d sys/uvm/uvm_amap.c
--- a/sys/uvm/uvm_amap.c        Thu Nov 14 17:11:54 2002 +0000
+++ b/sys/uvm/uvm_amap.c        Thu Nov 14 17:58:48 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_amap.c,v 1.45 2002/09/15 16:54:27 chs Exp $        */
+/*     $NetBSD: uvm_amap.c,v 1.46 2002/11/14 17:58:49 atatat Exp $     */
 
 /*
  *
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.45 2002/09/15 16:54:27 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_amap.c,v 1.46 2002/11/14 17:58:49 atatat Exp $");
 
 #undef UVM_AMAP_INLINE         /* enable/disable amap inlines */
 
@@ -284,21 +284,24 @@
  *    one (thus it can't be shared)
  */
 int
-amap_extend(entry, addsize)
+amap_extend(entry, addsize, forwards)
        struct vm_map_entry *entry;
        vsize_t addsize;
+       int forwards;
 {
        struct vm_amap *amap = entry->aref.ar_amap;
        int slotoff = entry->aref.ar_pageoff;
        int slotmapped, slotadd, slotneed, slotadded, slotalloc;
+       int slotadj, slotspace;
 #ifdef UVM_AMAP_PPREF
        int *newppref, *oldppref;
 #endif
-       int *newsl, *newbck, *oldsl, *oldbck;
+       int i, *newsl, *newbck, *oldsl, *oldbck;
        struct vm_anon **newover, **oldover;
        UVMHIST_FUNC("amap_extend"); UVMHIST_CALLED(maphist);
 
-       UVMHIST_LOG(maphist, "  (entry=0x%x, addsize=0x%x)", entry,addsize,0,0);
+       UVMHIST_LOG(maphist, "  (entry=0x%x, addsize=0x%x, forwards=%d)",
+           entry, addsize, forwards, 0);
 
        /*
         * first, determine how many slots we need in the amap.  don't
@@ -309,7 +312,16 @@
        amap_lock(amap);
        AMAP_B2SLOT(slotmapped, entry->end - entry->start); /* slots mapped */
        AMAP_B2SLOT(slotadd, addsize);                  /* slots to add */
-       slotneed = slotoff + slotmapped + slotadd;
+       if (forwards) {
+               slotneed = slotoff + slotmapped + slotadd;
+               slotadj = 0;
+               slotspace = 0;
+       }
+       else {
+               slotneed = slotadd + slotmapped;
+               slotadj = slotadd - slotoff;
+               slotspace = amap->am_maxslot - slotmapped;
+       }
 
        /*
         * case 1: we already have enough slots in the map and thus
@@ -317,16 +329,35 @@
         * adding.
         */
 
-       if (amap->am_nslot >= slotneed) {
+       if (forwards) {
+               if (amap->am_nslot >= slotneed) {
 #ifdef UVM_AMAP_PPREF
-               if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
-                       amap_pp_adjref(amap, slotoff + slotmapped, slotadd, 1);
+                       if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
+                               amap_pp_adjref(amap, slotoff + slotmapped,
+                                   slotadd, 1);
+                       }
+#endif
+                       amap_unlock(amap);
+                       UVMHIST_LOG(maphist,
+                           "<- done (case 1f), amap = 0x%x, sltneed=%d",
+                           amap, slotneed, 0, 0);
+                       return 0;
                }
+       } else {
+               if (slotadj <= 0) {
+                       slotoff -= slotadd;
+                       entry->aref.ar_pageoff = slotoff;
+#ifdef UVM_AMAP_PPREF
+                       if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
+                               amap_pp_adjref(amap, slotoff, slotadd, 1);
+                       }
 #endif
-               amap_unlock(amap);
-               UVMHIST_LOG(maphist,"<- done (case 1), amap = 0x%x, sltneed=%d",
-                   amap, slotneed, 0, 0);
-               return 0;
+                       amap_unlock(amap);
+                       UVMHIST_LOG(maphist,
+                           "<- done (case 1b), amap = 0x%x, sltneed=%d",
+                           amap, slotneed, 0, 0);
+                       return 0;
+               }
        }
 
        /*
@@ -335,27 +366,87 @@
         */
 
        if (amap->am_maxslot >= slotneed) {
+               if (forwards) {
 #ifdef UVM_AMAP_PPREF
-               if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
-                       if ((slotoff + slotmapped) < amap->am_nslot)
-                               amap_pp_adjref(amap, slotoff + slotmapped,
-                                   (amap->am_nslot - (slotoff + slotmapped)),
-                                   1);
-                       pp_setreflen(amap->am_ppref, amap->am_nslot, 1,
-                          slotneed - amap->am_nslot);
-               }
+                       if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
+                               if ((slotoff + slotmapped) < amap->am_nslot)
+                                       amap_pp_adjref(amap,
+                                           slotoff + slotmapped,
+                                           (amap->am_nslot -
+                                           (slotoff + slotmapped)), 1);
+                               pp_setreflen(amap->am_ppref, amap->am_nslot, 1,
+                                   slotneed - amap->am_nslot);
+                       }
 #endif
-               amap->am_nslot = slotneed;
-               amap_unlock(amap);
+                       amap->am_nslot = slotneed;
+                       amap_unlock(amap);
+
+                       /*
+                        * no need to zero am_anon since that was done at
+                        * alloc time and we never shrink an allocation.
+                        */
+
+                       UVMHIST_LOG(maphist,"<- done (case 2f), amap = 0x%x, "
+                           "slotneed=%d", amap, slotneed, 0, 0);
+                       return 0;
+               } else {
+#ifdef UVM_AMAP_PPREF
+                       if (amap->am_ppref && amap->am_ppref != PPREF_NONE) {
+                               /*
+                                * Slide up the ref counts on the pages that
+                                * are actually in use.
+                                */
+                               memmove(amap->am_ppref + slotspace,
+                                   amap->am_ppref + slotoff,
+                                   slotmapped * sizeof(int));
+                               /*
+                                * Mark the (adjusted) gap at the front as
+                                * referenced/not referenced.
+                                */
+                               pp_setreflen(amap->am_ppref,
+                                   0, 0, slotspace - slotadd);
+                               pp_setreflen(amap->am_ppref,
+                                   slotspace - slotadd, 1, slotadd);
+                       }
+#endif
 
-               /*
-                * no need to zero am_anon since that was done at
-                * alloc time and we never shrink an allocation.
-                */
+                       /*
+                        * Slide the anon pointers up and clear out
+                        * the space we just made.
+                        */
+                       memmove(amap->am_anon + slotspace,
+                           amap->am_anon + slotoff,
+                           slotmapped * sizeof(struct vm_anon*));
+                       memset(amap->am_anon + slotoff, 0,
+                           (slotspace - slotoff) * sizeof(struct vm_anon *));
+
+                       /*
+                        * Slide the backpointers up, but don't bother
+                        * wiping out the old slots.
+                        */
+                       memmove(amap->am_bckptr + slotspace,
+                           amap->am_bckptr + slotoff,
+                           slotmapped * sizeof(int));
 
-               UVMHIST_LOG(maphist,"<- done (case 2), amap = 0x%x, "
-                   "slotneed=%d", amap, slotneed, 0, 0);
-               return 0;
+                       /*
+                        * Adjust all the useful active slot numbers.
+                        */
+                       for (i = 0; i < amap->am_nused; i++)
+                               amap->am_slots[i] += (slotspace - slotoff);
+
+                       /*
+                        * We just filled all the empty space in the
+                        * front of the amap by activating a few new
+                        * slots.
+                        */
+                       amap->am_nslot = amap->am_maxslot;
+                       entry->aref.ar_pageoff = slotspace - slotadd;
+                       amap_unlock(amap);
+
+                       UVMHIST_LOG(maphist,"<- done (case 2b), amap = 0x%x, "
+                           "slotneed=%d", amap, slotneed, 0, 0);
+                       return 0;
+               }
        }
 
        /*
@@ -385,6 +476,11 @@
        newover = malloc(slotalloc * sizeof(struct vm_anon *), M_UVMAMAP,
            M_WAITOK | M_CANFAIL);
        if (newsl == NULL || newbck == NULL || newover == NULL) {
+#ifdef UVM_AMAP_PPREF
+               if (newppref != NULL) {
+                       free(amap->am_ppref, M_UVMAMAP);
+               }
+#endif
                if (newsl != NULL) {
                        free(newsl, M_UVMAMAP);
                }
@@ -404,41 +500,78 @@
         */
 
        slotadded = slotalloc - amap->am_nslot;
+       if (!forwards)
+               slotspace = slotalloc - slotmapped;
 
        /* do am_slots */
        oldsl = amap->am_slots;
-       memcpy(newsl, oldsl, sizeof(int) * amap->am_nused);
+       if (forwards)
+               memcpy(newsl, oldsl, sizeof(int) * amap->am_nused);
+       else
+               for (i = 0; i < amap->am_nused; i++)
+                       newsl[i] = oldsl[i] + slotspace - slotoff;
        amap->am_slots = newsl;
 
        /* do am_anon */
        oldover = amap->am_anon;
-       memcpy(newover, oldover, sizeof(struct vm_anon *) * amap->am_nslot);
-       memset(newover + amap->am_nslot, 0, sizeof(struct vm_anon *) *
-           slotadded);
+       if (forwards) {
+               memcpy(newover, oldover,
+                   sizeof(struct vm_anon *) * amap->am_nslot);
+               memset(newover + amap->am_nslot, 0,
+                   sizeof(struct vm_anon *) * slotadded);
+       } else {
+               memcpy(newover + slotspace, oldover + slotoff,
+                   sizeof(struct vm_anon *) * slotmapped);
+               memset(newover, 0,
+                   sizeof(struct vm_anon *) * slotspace);
+       }
        amap->am_anon = newover;
 
        /* do am_bckptr */
        oldbck = amap->am_bckptr;
-       memcpy(newbck, oldbck, sizeof(int) * amap->am_nslot);
+       if (forwards)
+               memcpy(newbck, oldbck, sizeof(int) * amap->am_nslot);
+       else
+               memcpy(newbck + slotspace, oldbck + slotoff,
+                   sizeof(int) * slotmapped);
        amap->am_bckptr = newbck;
 
 #ifdef UVM_AMAP_PPREF
        /* do ppref */
        oldppref = amap->am_ppref;
        if (newppref) {
-               memcpy(newppref, oldppref, sizeof(int) * amap->am_nslot);
-               memset(newppref + amap->am_nslot, 0, sizeof(int) * slotadded);
+               if (forwards) {
+                       memcpy(newppref, oldppref,
+                           sizeof(int) * amap->am_nslot);
+                       memset(newppref + amap->am_nslot, 0,
+                           sizeof(int) * slotadded);
+               } else {
+                       memcpy(newppref + slotspace, oldppref + slotoff,
+                           sizeof(int) * slotmapped);
+               }
                amap->am_ppref = newppref;
-               if ((slotoff + slotmapped) < amap->am_nslot)
+               if (forwards && (slotoff + slotmapped) < amap->am_nslot)
                        amap_pp_adjref(amap, slotoff + slotmapped,
                            (amap->am_nslot - (slotoff + slotmapped)), 1);
-               pp_setreflen(newppref, amap->am_nslot, 1,
-                   slotneed - amap->am_nslot);
+               if (forwards)
+                       pp_setreflen(newppref, amap->am_nslot, 1,
+                           slotneed - amap->am_nslot);
+               else {
+                       pp_setreflen(newppref, 0, 0,
+                           slotalloc - slotneed);
+                       pp_setreflen(newppref, slotalloc - slotneed, 1,
+                           slotneed - slotmapped);
+               }



Home | Main Index | Thread Index | Old Index