Module Name: src
Committed By: matt
Date: Sat Jan 23 19:54:04 UTC 2010
Modified Files:
src/sys/uvm [matt-nb5-mips64]: uvm_page.h uvm_pglist.c
Log Message:
Add a start_hint to vm_physseg so when allocating pages, we can skip
forward over pages that are probably still allocated.
To generate a diff of this commit:
cvs rdiff -u -r1.55 -r1.55.14.1 src/sys/uvm/uvm_page.h
cvs rdiff -u -r1.42.16.3 -r1.42.16.4 src/sys/uvm/uvm_pglist.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/uvm/uvm_page.h
diff -u src/sys/uvm/uvm_page.h:1.55 src/sys/uvm/uvm_page.h:1.55.14.1
--- src/sys/uvm/uvm_page.h:1.55 Wed Jun 4 15:06:04 2008
+++ src/sys/uvm/uvm_page.h Sat Jan 23 19:54:04 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_page.h,v 1.55 2008/06/04 15:06:04 ad Exp $ */
+/* $NetBSD: uvm_page.h,v 1.55.14.1 2010/01/23 19:54:04 matt Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -234,9 +234,11 @@
paddr_t end; /* (PF# of last page in segment) + 1 */
paddr_t avail_start; /* PF# of first free page in segment */
paddr_t avail_end; /* (PF# of last free page in segment) +1 */
- int free_list; /* which free list they belong on */
struct vm_page *pgs; /* vm_page structures (from start) */
struct vm_page *lastpg; /* vm_page structure for end */
+ int free_list; /* which free list they belong on */
+ u_int start_hint; /* start looking for free pages here */
+ /* protected by uvm_fpageqlock */
#ifdef __HAVE_PMAP_PHYSSEG
struct pmap_physseg pmseg; /* pmap specific (MD) data */
#endif
Index: src/sys/uvm/uvm_pglist.c
diff -u src/sys/uvm/uvm_pglist.c:1.42.16.3 src/sys/uvm/uvm_pglist.c:1.42.16.4
--- src/sys/uvm/uvm_pglist.c:1.42.16.3 Fri Jan 22 08:54:41 2010
+++ src/sys/uvm/uvm_pglist.c Sat Jan 23 19:54:04 2010
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_pglist.c,v 1.42.16.3 2010/01/22 08:54:41 matt Exp $ */
+/* $NetBSD: uvm_pglist.c,v 1.42.16.4 2010/01/23 19:54:04 matt Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.42.16.3 2010/01/22 08:54:41 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.42.16.4 2010/01/23 19:54:04 matt Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -122,9 +122,9 @@
paddr_t alignment, paddr_t boundary, struct pglist *rlist)
{
signed int try, limit, tryidx, end, idx, skip;
- const signed int align = atop(alignment);
struct vm_page *pgs;
int pagemask;
+ bool second_pass;
#ifdef DEBUG
paddr_t idxpa, lastidxpa;
int cidx = 0; /* XXX: GCC */
@@ -136,20 +136,42 @@
KASSERT(mutex_owned(&uvm_fpageqlock));
- try = roundup(max(atop(low), ps->avail_start), align);
- limit = min(atop(high), ps->avail_end);
+ low = atop(low);
+ high = atop(high);
+ alignment = atop(alignment);
+
+ /*
+ * We start our search at the just after where the last allocation
+ * succeeded.
+ */
+ try = roundup(max(low, ps->avail_start + ps->start_hint), alignment);
+ limit = min(high, ps->avail_end);
pagemask = ~((boundary >> PAGE_SHIFT) - 1);
skip = 0;
+ second_pass = true;
+ pgs = ps->pgs;
for (;;) {
bool ok = true;
- int cnt;
+ signed int cnt;
if (try + num > limit) {
+ if (ps->start_hint == 0 || second_pass) {
+ /*
+ * We've run past the allowable range.
+ */
+ return 0; /* FAIL = 0 pages*/
+ }
/*
- * We've run past the allowable range.
+ * We've wrapped around the end of this segment
+ * so restart at the beginning but now our limit
+ * is were we started.
*/
- return (0); /* FAIL */
+ second_pass = true;
+ try = roundup(max(low, ps->avail_start), alignment);
+ limit = min(high, ps->avail_start + ps->start_hint);
+ skip = 0;
+ continue;
}
if (boundary != 0 &&
((try ^ (try + num - 1)) & pagemask) != 0) {
@@ -158,7 +180,8 @@
* just crossed and ensure alignment.
*/
try = (try + num - 1) & pagemask;
- try = roundup(try, align);
+ try = roundup(try, alignment);
+ skip = 0;
continue;
}
#ifdef DEBUG
@@ -177,14 +200,13 @@
#endif
tryidx = try - ps->start;
end = tryidx + num;
- pgs = ps->pgs;
/*
* Found a suitable starting page. See if the range is free.
*/
#ifdef PGALLOC_VERBOSE
printf("%s: ps=%p try=%#x end=%#x skip=%#x, align=%#x",
- __func__, ps, tryidx, end, skip, align);
+ __func__, ps, tryidx, end, skip, alignment);
#endif
/*
* We start at the end and work backwards since if we find a
@@ -243,7 +265,7 @@
/*
* now round up that to the needed alignment.
*/
- cnt = roundup(cnt, align);
+ cnt = roundup(cnt, alignment);
/*
* The number of pages we can skip checking
* (might be 0 if cnt > num).
@@ -258,10 +280,16 @@
for (idx = tryidx, pgs += idx; idx < end; idx++, pgs++)
uvm_pglist_add(pgs, rlist);
+ /*
+ * the next time we need to search this segment, start after this
+ * chunk of pages we just allocated.
+ */
+ ps->start_hint = tryidx + num;
+
#ifdef PGALLOC_VERBOSE
printf("got %d pgs\n", num);
#endif
- return (num); /* number of pages allocated */
+ return num; /* number of pages allocated */
}
static int
@@ -327,6 +355,7 @@
{
int todo, limit, try;
struct vm_page *pg;
+ bool second_pass;
#ifdef DEBUG
int cidx = 0; /* XXX: GCC */
#endif
@@ -337,26 +366,45 @@
KASSERT(mutex_owned(&uvm_fpageqlock));
+ low = atop(low);
+ high = atop(high);
todo = num;
- limit = min(atop(high), ps->avail_end);
-
- for (try = max(atop(low), ps->avail_start);
- try < limit; try ++) {
+ try = max(low, ps->avail_start + ps->start_hint);
+ limit = min(high, ps->avail_end);
+ pg = &ps->pgs[try - ps->start];
+ second_pass = false;
+
+ for (;; try++, pg++) {
+ if (try >= limit) {
+ if (ps->start_hint == 0 || second_pass)
+ break;
+ second_pass = true;
+ try = max(low, ps->avail_start);
+ limit = min(high, ps->avail_start + ps->start_hint);
+ pg = &ps->pgs[try - ps->start];
+ continue;
+ }
#ifdef DEBUG
if (vm_physseg_find(try, &cidx) != ps - vm_physmem)
panic("pgalloc simple: botch1");
if (cidx != (try - ps->start))
panic("pgalloc simple: botch2");
#endif
- 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;
+ }
}
+ /*
+ * The next time we need to search this segment,
+ * start just after the pages we just allocated.
+ */
+ ps->start_hint = try + 1 - ps->start;
+
#ifdef PGALLOC_VERBOSE
printf("got %d pgs\n", num - todo);
#endif