Source-Changes-HG archive

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

[src/trunk]: src/sys/uvm Big cleanup and speed improvements to pglist_alloc c...



details:   https://anonhg.NetBSD.org/src/rev/bb7f912d388b
branches:  trunk
changeset: 533329:bb7f912d388b
user:      drochner <drochner%NetBSD.org@localhost>
date:      Thu Jun 27 18:05:29 2002 +0000

description:
Big cleanup and speed improvements to pglist_alloc code:
-pass vm_physseg* instead of physseg index, and PFN (int) instead
 of physical address (could be done even more)
-simplify detection of boundary crossing and behave more intelligently
 in this case
-take stuff out of the inner loops, or put into "#ifdef DEBUG"
 (because we move along physsegs we don't need to check that the
  pages are physically contigous)
-make the "simple" and "contigous" branches look more uniform; at
 least the outer loops might coalesce one day

diffstat:

 sys/uvm/uvm_pglist.c |  178 ++++++++++++++++++++++++++++----------------------
 1 files changed, 101 insertions(+), 77 deletions(-)

diffs (truncated from 365 to 300 lines):

diff -r 1db20d414701 -r bb7f912d388b sys/uvm/uvm_pglist.c
--- a/sys/uvm/uvm_pglist.c      Thu Jun 27 17:31:25 2002 +0000
+++ b/sys/uvm/uvm_pglist.c      Thu Jun 27 18:05:29 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uvm_pglist.c,v 1.23 2002/06/20 08:24:22 enami Exp $    */
+/*     $NetBSD: uvm_pglist.c,v 1.24 2002/06/27 18:05:29 drochner Exp $ */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.23 2002/06/20 08:24:22 enami Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.24 2002/06/27 18:05:29 drochner Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -85,13 +85,13 @@
  */
 
 static void uvm_pglist_add(struct vm_page *, struct pglist *);
-static int uvm_pglistalloc_c_ps(int, psize_t, paddr_t, paddr_t,
+static int uvm_pglistalloc_c_ps(struct vm_physseg *, int, paddr_t, paddr_t,
                                paddr_t, paddr_t, struct pglist *);
-static int uvm_pglistalloc_contig(psize_t, paddr_t, paddr_t, paddr_t, paddr_t,
+static int uvm_pglistalloc_contig(int, paddr_t, paddr_t, paddr_t, paddr_t,
                                  struct pglist *);
-static void uvm_pglistalloc_s_ps(int, paddr_t, paddr_t,
-                                struct pglist *, int *);
-static int uvm_pglistalloc_simple(psize_t, paddr_t, paddr_t,
+static int uvm_pglistalloc_s_ps(struct vm_physseg *, int, paddr_t, paddr_t,
+                               struct pglist *);
+static int uvm_pglistalloc_simple(int, paddr_t, paddr_t,
                                  struct pglist *, int);
 
 static void
@@ -136,115 +136,125 @@
 }
 
 static int
-uvm_pglistalloc_c_ps(psi, size, low, high, alignment, boundary, rlist)
-       int psi;
-       psize_t size;
+uvm_pglistalloc_c_ps(ps, num, low, high, alignment, boundary, rlist)
+       struct vm_physseg *ps;
+       int num;
        paddr_t low, high, alignment, boundary;
        struct pglist *rlist;
 {
        int try, limit, tryidx, end, idx;
        struct vm_page *pgs;
+       int pagemask;
+#ifdef DEBUG
        paddr_t idxpa, lastidxpa;
-       u_long pagemask;
-#ifdef DEBUG
        int cidx;
 #endif
+#ifdef PGALLOC_VERBOSE
+       printf("pgalloc: contig %d pgs from psi %d\n", num, ps - vm_physmem);
+#endif
 
-       limit = min(atop(high), vm_physmem[psi].avail_end);
-       pagemask = ~(boundary - 1);
+       try = roundup(max(atop(low), ps->avail_start), atop(alignment));
+       limit = min(atop(high), ps->avail_end);
+       pagemask = ~((boundary >> PAGE_SHIFT) - 1);
 
-       for (try = roundup(max(atop(low), vm_physmem[psi].avail_start),
-                          atop(alignment));; try += atop(alignment)) {
-               if (try + atop(size) >= limit) {
-
+       for (;;) {
+               if (try + num > limit) {
                        /*
                         * We've run past the allowable range.
                         */
-
                        return (0); /* FAIL */
                }
+               if (boundary != 0 &&
+                   ((try ^ (try + num - 1)) & pagemask) != 0) {
+                       /*
+                        * Region crosses boundary. Jump to the boundary
+                        * just crossed and ensure alignment.
+                        */
+                       try = (try + num - 1) & pagemask;
+                       try = roundup(try, atop(alignment));
+                       continue;
+               }
 #ifdef DEBUG
                /*
                 * Make sure this is a managed physical page.
                 */
 
-               if (vm_physseg_find(try, &cidx) != psi)
+               if (vm_physseg_find(try, &cidx) != ps - vm_physmem)
                        panic("pgalloc contig: botch1");
-               if (cidx != try - vm_physmem[psi].start)
+               if (cidx != try - ps->start)
                        panic("pgalloc contig: botch2");
-               if (vm_physseg_find(try + atop(size), &cidx) != psi)
+               if (vm_physseg_find(try + num - 1, &cidx) != ps - vm_physmem)
                        panic("pgalloc contig: botch3");
-               if (cidx != try - vm_physmem[psi].start + atop(size))
+               if (cidx != try - ps->start + num - 1)
                        panic("pgalloc contig: botch4");                
 #endif
-               tryidx = try - vm_physmem[psi].start;
-               end = tryidx + (size >> PAGE_SHIFT);
-               pgs = vm_physmem[psi].pgs;
+               tryidx = try - ps->start;
+               end = tryidx + num;
+               pgs = ps->pgs;
 
                /*
-                * Found a suitable starting page.  See of the range is free.
+                * Found a suitable starting page.  See if the range is free.
                 */
-
                for (idx = tryidx; idx < end; idx++) {
-                       if (VM_PAGE_IS_FREE(&pgs[idx]) == 0) {
+                       if (VM_PAGE_IS_FREE(&pgs[idx]) == 0)
                                break;
-                       }
+
+#ifdef DEBUG
                        idxpa = VM_PAGE_TO_PHYS(&pgs[idx]);
                        if (idx > tryidx) {
                                lastidxpa = VM_PAGE_TO_PHYS(&pgs[idx - 1]);
                                if ((lastidxpa + PAGE_SIZE) != idxpa) {
-
                                        /*
                                         * Region not contiguous.
                                         */
-
                                        panic("pgalloc contig: botch5");
                                }
                                if (boundary != 0 &&
-                                   ((lastidxpa ^ idxpa) & pagemask) != 0) {
-
+                                   ((lastidxpa ^ idxpa) & ~(boundary - 1))
+                                   != 0) {
                                        /*
                                         * Region crosses boundary.
                                         */
-
-                                       break;
+                                       panic("pgalloc contig: botch6");
                                }
                        }
+#endif
                }
-               if (idx == end) {
+               if (idx == end)
                        break;
-               }
+
+               try += atop(alignment);
        }
 
        /*
         * we have a chunk of memory that conforms to the requested constraints.
         */
        idx = tryidx;
-       while (idx < end) {
+       while (idx < end)
                uvm_pglist_add(&pgs[idx++], rlist);
-       }
-       return (1);
+
+#ifdef PGALLOC_VERBOSE
+       printf("got %d pgs\n", num);
+#endif
+       return (num); /* number of pages allocated */
 }
 
 static int
-uvm_pglistalloc_contig(size, low, high, alignment, boundary, rlist)
-       psize_t size;
+uvm_pglistalloc_contig(num, low, high, alignment, boundary, rlist)
+       int num;
        paddr_t low, high, alignment, boundary;
        struct pglist *rlist;
 {
        int fl, psi;
+       struct vm_physseg *ps;
        int s, error;
 
-       if (boundary != 0 && boundary < size)
-               return (EINVAL);
-
        /* Default to "lose". */
        error = ENOMEM;
 
        /*
         * Block all memory allocation and lock the free list.
         */
-
        s = uvm_lock_fpageq();
 
        /* Are there even any free pages? */
@@ -258,12 +268,15 @@
                for (psi = 0 ; psi < vm_nphysseg ; psi++)
 #endif
                {
-                       if (vm_physmem[psi].free_list != fl)
+                       ps = &vm_physmem[psi];
+
+                       if (ps->free_list != fl)
                                continue;
 
-                       if (uvm_pglistalloc_c_ps(psi, size, low, high,
-                                                alignment, boundary, rlist)) {
-#if 0
+                       num -= uvm_pglistalloc_c_ps(ps, num, low, high,
+                                                   alignment, boundary, rlist);
+                       if (num == 0) {
+#ifdef PGALLOC_VERBOSE
                                printf("pgalloc: %lx-%lx\n",
                                       TAILQ_FIRST(rlist)->phys_addr,
                                       TAILQ_LAST(rlist, pglist)->phys_addr);
@@ -285,58 +298,65 @@
        return (error);
 }
 
-static void
-uvm_pglistalloc_s_ps(psi, low, high, rlist, todo)
-       int psi;
+static int
+uvm_pglistalloc_s_ps(ps, num, low, high, rlist)
+       struct vm_physseg *ps;
+       int num;
        paddr_t low, high;
        struct pglist *rlist;
-       int *todo;
 {
-       int limit, try;
+       int todo, limit, try;
        struct vm_page *pg;
 #ifdef DEBUG
        int cidx;
 #endif
+#ifdef PGALLOC_VERBOSE
+       printf("pgalloc: simple %d pgs from psi %d\n", num, ps - vm_physmem);
+#endif
 
-       limit = min(atop(high), vm_physmem[psi].avail_end);
+       todo = num;
+       limit = min(atop(high), ps->avail_end);
 
-       for (try = max(atop(low), vm_physmem[psi].avail_start);
+       for (try = max(atop(low), ps->avail_start);
             try < limit; try ++) {
 #ifdef DEBUG
-               if (vm_physseg_find(try, &cidx) != psi)
+               if (vm_physseg_find(try, &cidx) != ps - vm_physmem)
                        panic("pgalloc simple: botch1");
-               if (cidx != (try - vm_physmem[psi].start))
+               if (cidx != (try - ps->start))
                        panic("pgalloc simple: botch2");
 #endif
-               pg = &vm_physmem[psi].pgs[try - vm_physmem[psi].start];
+               pg = &ps->pgs[try - ps->start];
                if (VM_PAGE_IS_FREE(pg) == 0)
                        continue;
 
                uvm_pglist_add(pg, rlist);
-               if (--(*todo) == 0)
+               if (--todo == 0)
                        break;
        }
+
+#ifdef PGALLOC_VERBOSE
+       printf("got %d pgs\n", num - todo);
+#endif
+       return (num - todo); /* number of pages allocated */
 }
 
 static int
-uvm_pglistalloc_simple(size, low, high, rlist, waitok)
-       psize_t size;
+uvm_pglistalloc_simple(num, low, high, rlist, waitok)
+       int num;
        paddr_t low, high;
        struct pglist *rlist;
        int waitok;
 {
-       int fl, psi, s, todo, error;
+       int fl, psi, s, error;
+       struct vm_physseg *ps;
 
        /* Default to "lose". */
        error = ENOMEM;
 
-       todo = size >> PAGE_SHIFT;
-
 again:
        /*



Home | Main Index | Thread Index | Old Index