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

Reply via email to