Source-Changes-HG archive

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

[src/trunk]: src/sys/uvm Support dynamic sizing of the page color bins. We a...



details:   https://anonhg.NetBSD.org/src/rev/d8e977e14d35
branches:  trunk
changeset: 509337:d8e977e14d35
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Wed May 02 01:22:19 2001 +0000

description:
Support dynamic sizing of the page color bins.  We also support
dynamically re-coloring pages; as machine-dependent code discovers
the size of the system's caches, it may call uvm_page_recolor() with
the new number of colors to use.  If the new mumber of colors is
smaller (or equal to) the current number of colors, then uvm_page_recolor()
is a no-op.

The system defaults to one bucket if machine-dependent code does not
initialize uvmexp.ncolors before uvm_page_init() is called.

Note that the number of color bins should be initialized to something
reasonable as early as possible -- for many early memory allocations,
we live with the consequences of the page choice for the lifetime of
the boot.

diffstat:

 sys/uvm/uvm_extern.h |    6 +-
 sys/uvm/uvm_page.c   |  142 ++++++++++++++++++++++++++++++++++++++++++++------
 sys/uvm/uvm_page.h   |    7 +-
 sys/uvm/uvm_param.h  |   14 +----
 sys/uvm/uvm_pglist.h |    4 +-
 5 files changed, 134 insertions(+), 39 deletions(-)

diffs (truncated from 323 to 300 lines):

diff -r 93d7fb105215 -r d8e977e14d35 sys/uvm/uvm_extern.h
--- a/sys/uvm/uvm_extern.h      Wed May 02 01:05:16 2001 +0000
+++ b/sys/uvm/uvm_extern.h      Wed May 02 01:22:19 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_extern.h,v 1.61 2001/05/01 19:36:56 thorpej Exp $  */
+/*     $NetBSD: uvm_extern.h,v 1.62 2001/05/02 01:22:19 thorpej Exp $  */
 
 /*
  *
@@ -252,6 +252,9 @@
        int paging;     /* number of pages in the process of being paged out */
        int wired;      /* number of wired pages */
 
+       int ncolors;    /* number of page color buckets: must be p-o-2 */
+       int colormask;  /* color bucket mask */
+
        /* 
         * Adding anything before this line will break binary compatibility
         * with top(1) on NetBSD 1.5.
@@ -310,7 +313,6 @@
                                   aborted */
        int colorhit;           /* pagealloc where we got optimal color */
        int colormiss;          /* pagealloc where we didn't */
-       int ncolors;            /* number of page color buckets */
 
        /* fault subcounters */
        int fltnoram;   /* number of times fault was out of ram */
diff -r 93d7fb105215 -r d8e977e14d35 sys/uvm/uvm_page.c
--- a/sys/uvm/uvm_page.c        Wed May 02 01:05:16 2001 +0000
+++ b/sys/uvm/uvm_page.c        Wed May 02 01:22:19 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_page.c,v 1.59 2001/05/01 19:36:57 thorpej Exp $    */
+/*     $NetBSD: uvm_page.c,v 1.60 2001/05/02 01:22:20 thorpej Exp $    */
 
 /* 
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -126,6 +126,16 @@
 static struct pglist uvm_bootbucket;
 
 /*
+ * we allocate an initial number of page colors in uvm_page_init(),
+ * and remember them.  We may re-color pages as cache sizes are
+ * discovered during the autoconfiguration phase.  But we can never
+ * free the initial set of buckets, since they are allocated using
+ * uvm_pageboot_alloc().
+ */
+
+static boolean_t have_recolored_pages /* = FALSE */;
+
+/*
  * local prototypes
  */
 
@@ -202,6 +212,19 @@
        pg->version++;
 }
 
+static void
+uvm_page_init_buckets(struct pgfreelist *pgfl)
+{
+       int color, i;
+
+       for (color = 0; color < uvmexp.ncolors; color++) {
+               for (i = 0; i < PGFL_NQUEUES; i++) {
+                       TAILQ_INIT(&pgfl->pgfl_buckets[
+                           color].pgfl_queues[i]);
+               }
+       }
+}
+
 /*
  * uvm_page_init: init the page system.   called from uvm_init().
  * 
@@ -212,24 +235,18 @@
 uvm_page_init(kvm_startp, kvm_endp)
        vaddr_t *kvm_startp, *kvm_endp;
 {
-       vsize_t freepages, pagecount, n;
+       vsize_t freepages, pagecount, bucketcount, n;
+       struct pgflbucket *bucketarray;
        vm_page_t pagearray;
-       int lcv, color, i;
+       int lcv, i;
        paddr_t paddr;
 
        /*
-        * init the page queues and page queue locks
+        * init the page queues and page queue locks, except the free
+        * list; we allocate that later (with the initial vm_page
+        * structures).
         */
 
-       uvmexp.ncolors = VM_PGCOLOR_BUCKETS;
-       for (lcv = 0; lcv < VM_NFREELIST; lcv++) {
-               for (color = 0; color < VM_PGCOLOR_BUCKETS; color++) {
-                       for (i = 0; i < PGFL_NQUEUES; i++) {
-                               TAILQ_INIT(&uvm.page_free[lcv].pgfl_buckets[
-                                   color].pgfl_queues[i]);
-                       }
-               }
-       }
        TAILQ_INIT(&uvm.page_active);
        TAILQ_INIT(&uvm.page_inactive_swp);
        TAILQ_INIT(&uvm.page_inactive_obj);
@@ -275,6 +292,14 @@
                freepages += (vm_physmem[lcv].end - vm_physmem[lcv].start);
 
        /*
+        * Let MD code initialize the number of colors, or default
+        * to 1 color if MD code doesn't care.
+        */
+       if (uvmexp.ncolors == 0)
+               uvmexp.ncolors = 1;
+       uvmexp.colormask = uvmexp.ncolors - 1;
+
+       /*
         * we now know we have (PAGE_SIZE * freepages) bytes of memory we can
         * use.   for each page of memory we use we need a vm_page structure.
         * thus, the total number of pages we can use is the total size of
@@ -284,10 +309,21 @@
         * pages).
         */
         
+       bucketcount = uvmexp.ncolors * VM_NFREELIST;
        pagecount = ((freepages + 1) << PAGE_SHIFT) /
            (PAGE_SIZE + sizeof(struct vm_page));
-       pagearray = (vm_page_t)uvm_pageboot_alloc(pagecount *
-           sizeof(struct vm_page));
+
+       bucketarray = (void *) uvm_pageboot_alloc((bucketcount *
+           sizeof(struct pgflbucket)) + (pagecount *
+           sizeof(struct vm_page)));
+       pagearray = (struct vm_page *)(bucketarray + bucketcount);
+
+       for (lcv = 0; lcv < VM_NFREELIST; lcv++) {
+               uvm.page_free[lcv].pgfl_buckets =
+                   (bucketarray + (lcv * uvmexp.ncolors));
+               uvm_page_init_buckets(&uvm.page_free[lcv]);
+       }
+
        memset(pagearray, 0, pagecount * sizeof(struct vm_page));
                                         
        /*
@@ -841,6 +877,76 @@
        return;
 }
 
+/*
+ * uvm_page_recolor: Recolor the pages if the new bucket count is
+ * larger than the old one.
+ */
+
+void
+uvm_page_recolor(int newncolors)
+{
+       struct pgflbucket *bucketarray, *oldbucketarray;
+       struct pgfreelist pgfl;
+       vm_page_t pg;
+       vsize_t bucketcount;
+       int s, lcv, color, i, ocolors;
+
+       if (newncolors <= uvmexp.ncolors)
+               return;
+
+       bucketcount = newncolors * VM_NFREELIST;
+       bucketarray = malloc(bucketcount * sizeof(struct pgflbucket),
+           M_VMPAGE, M_NOWAIT);
+       if (bucketarray == NULL) {
+               printf("WARNING: unable to allocate %ld page color buckets\n",
+                   (long) bucketcount);
+               return;
+       }
+
+       s = uvm_lock_fpageq();
+
+       /* Make sure we should still do this. */
+       if (newncolors <= uvmexp.ncolors) {
+               uvm_unlock_fpageq(s);
+               free(bucketarray, M_VMPAGE);
+               return;
+       }
+
+       oldbucketarray = uvm.page_free[0].pgfl_buckets;
+       ocolors = uvmexp.ncolors;
+
+       uvmexp.ncolors = newncolors;
+       uvmexp.colormask = uvmexp.ncolors - 1;
+
+       for (lcv = 0; lcv < VM_NFREELIST; lcv++) {
+               pgfl.pgfl_buckets = (bucketarray + (lcv * newncolors));
+               uvm_page_init_buckets(&pgfl);
+               for (color = 0; color < ocolors; color++) {
+                       for (i = 0; i < PGFL_NQUEUES; i++) {
+                               while ((pg = TAILQ_FIRST(&uvm.page_free[
+                                   lcv].pgfl_buckets[color].pgfl_queues[i]))
+                                   != NULL) {
+                                       TAILQ_REMOVE(&uvm.page_free[
+                                           lcv].pgfl_buckets[
+                                           color].pgfl_queues[i], pg, pageq);
+                                       TAILQ_INSERT_TAIL(&pgfl.pgfl_buckets[
+                                           VM_PGCOLOR_BUCKET(pg)].pgfl_queues[
+                                           i], pg, pageq);
+                               }
+                       }
+               }
+               uvm.page_free[lcv].pgfl_buckets = pgfl.pgfl_buckets;
+       }
+
+       if (have_recolored_pages) {
+               uvm_unlock_fpageq(s);
+               free(oldbucketarray, M_VMPAGE);
+               return;
+       }
+
+       have_recolored_pages = TRUE;
+       uvm_unlock_fpageq(s);
+}
 
 #if 1 /* XXXCDC: TMP TMP TMP DEBUG DEBUG DEBUG */
 
@@ -891,7 +997,7 @@
                if ((pg = TAILQ_FIRST((freeq =
                    &pgfl->pgfl_buckets[color].pgfl_queues[try2]))) != NULL)
                        goto gotit;
-               color = (color + 1) & VM_PGCOLOR_MASK;
+               color = (color + 1) & uvmexp.colormask;
        } while (color != trycolor);
 
        return (NULL);
@@ -1046,7 +1152,7 @@
         * We now know which color we actually allocated from; set
         * the next color accordingly.
         */
-       uvm.page_free_nextcolor = (color + 1) & VM_PGCOLOR_MASK;
+       uvm.page_free_nextcolor = (color + 1) & uvmexp.colormask;
 
        /*
         * update allocation statistics and remember if we have to
@@ -1420,7 +1526,7 @@
                        }
                }
 
-               nextbucket = (nextbucket + 1) & VM_PGCOLOR_MASK;
+               nextbucket = (nextbucket + 1) & uvmexp.colormask;
        } while (nextbucket != firstbucket);
 
        uvm_unlock_fpageq(s);
diff -r 93d7fb105215 -r d8e977e14d35 sys/uvm/uvm_page.h
--- a/sys/uvm/uvm_page.h        Wed May 02 01:05:16 2001 +0000
+++ b/sys/uvm/uvm_page.h        Wed May 02 01:22:19 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_page.h,v 1.23 2001/05/01 03:01:18 thorpej Exp $    */
+/*     $NetBSD: uvm_page.h,v 1.24 2001/05/02 01:22:20 thorpej Exp $    */
 
 /* 
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -273,6 +273,7 @@
 boolean_t uvm_page_physget __P((paddr_t *));
 #endif
 void uvm_page_rehash __P((void));
+void uvm_page_recolor __P((int));
 void uvm_pageidlezero __P((void));
 
 PAGE_INLINE int uvm_lock_fpageq __P((void));
@@ -312,11 +313,9 @@
 
 /*
  * Compute the page color bucket for a given page.
- *
- * The constants we uses here come from <uvm/uvm_param.h>.
  */
 #define        VM_PGCOLOR_BUCKET(pg) \
-       (atop(VM_PAGE_TO_PHYS((pg))) & VM_PGCOLOR_MASK)
+       (atop(VM_PAGE_TO_PHYS((pg))) & uvmexp.colormask)
 
 /*
  * when VM_PHYSSEG_MAX is 1, we can simplify these functions
diff -r 93d7fb105215 -r d8e977e14d35 sys/uvm/uvm_param.h
--- a/sys/uvm/uvm_param.h       Wed May 02 01:05:16 2001 +0000
+++ b/sys/uvm/uvm_param.h       Wed May 02 01:22:19 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_param.h,v 1.8 2001/04/29 04:23:21 thorpej Exp $    */
+/*     $NetBSD: uvm_param.h,v 1.9 2001/05/02 01:22:20 thorpej Exp $    */
 
 /* 
  * Copyright (c) 1991, 1993
@@ -102,18 +102,6 @@
 #endif /* _KERNEL */
 
 /*
- * Page coloring parameters.  We let machine dependent code tell us how
- * many buckets to create.  If it doesn't, we assume it doesn't want to
- * do coloring, so we disable it (set the number of buckets to 1).
- *
- * Note: the number of buckets must be a power of two.
- */
-#ifndef VM_PGCOLOR_BUCKETS
-#define        VM_PGCOLOR_BUCKETS      1
-#endif
-#define        VM_PGCOLOR_MASK         (VM_PGCOLOR_BUCKETS - 1)



Home | Main Index | Thread Index | Old Index