svn commit: r208794 - in head/sys: mips/mips vm

Jayachandran C. jchandra at FreeBSD.org
Fri Jun 4 06:35:37 UTC 2010


Author: jchandra
Date: Fri Jun  4 06:35:36 2010
New Revision: 208794
URL: http://svn.freebsd.org/changeset/base/208794

Log:
  Make vm_contig_grow_cache() extern, and use it when vm_phys_alloc_contig()
  fails to allocate MIPS page table pages.  The current usage of VM_WAIT in
  case of vm_phys_alloc_contig() failure is not correct, because:
  
  "There is no guarantee that any of the available free (or cached) pages
  after the VM_WAIT will fall within the range of suitable physical
  addresses.  Every time this function sleeps and a single page is freed
  (or cached) by someone else, this function will be reawakened.  With
  a little bad luck, you could spin indefinitely."
  
  We also add low and high parameters to vm_contig_grow_cache() and
  vm_contig_launder() so that we restrict vm_contig_launder() to the range
  of pages we are interested in.
  
  Reported by: alc
  
  Reviewed by:	alc
  Approved by:	rrs (mentor)

Modified:
  head/sys/mips/mips/pmap.c
  head/sys/vm/vm_contig.c
  head/sys/vm/vm_pageout.h

Modified: head/sys/mips/mips/pmap.c
==============================================================================
--- head/sys/mips/mips/pmap.c	Thu Jun  3 21:12:51 2010	(r208793)
+++ head/sys/mips/mips/pmap.c	Fri Jun  4 06:35:36 2010	(r208794)
@@ -967,19 +967,23 @@ pmap_ptpgzone_allocf(uma_zone_t zone, in
 {
 	vm_page_t m;
 	vm_paddr_t paddr;
+	int tries;
 	
 	KASSERT(bytes == PAGE_SIZE,
 		("pmap_ptpgzone_allocf: invalid allocation size %d", bytes));
 
 	*flags = UMA_SLAB_PRIV;
-	for (;;) {
-		m = vm_phys_alloc_contig(1, 0, MIPS_KSEG0_LARGEST_PHYS,
-		    PAGE_SIZE, PAGE_SIZE);
-		if (m != NULL)
-			break;
-		if ((wait & M_WAITOK) == 0)
+	tries = 0;
+retry:
+	m = vm_phys_alloc_contig(1, 0, MIPS_KSEG0_LARGEST_PHYS,
+	    PAGE_SIZE, PAGE_SIZE);
+	if (m == NULL) {
+                if (tries < ((wait & M_NOWAIT) != 0 ? 1 : 3)) {
+			vm_contig_grow_cache(tries, 0, MIPS_KSEG0_LARGEST_PHYS);
+			tries++;
+			goto retry;
+		} else
 			return (NULL);
-		VM_WAIT;
 	}
 
 	paddr = VM_PAGE_TO_PHYS(m);

Modified: head/sys/vm/vm_contig.c
==============================================================================
--- head/sys/vm/vm_contig.c	Thu Jun  3 21:12:51 2010	(r208793)
+++ head/sys/vm/vm_contig.c	Fri Jun  4 06:35:36 2010	(r208794)
@@ -87,8 +87,6 @@ __FBSDID("$FreeBSD$");
 #include <vm/vm_phys.h>
 #include <vm/vm_extern.h>
 
-static void vm_contig_grow_cache(int tries);
-
 static int
 vm_contig_launder_page(vm_page_t m, vm_page_t *next)
 {
@@ -157,9 +155,10 @@ vm_contig_launder_page(vm_page_t m, vm_p
 }
 
 static int
-vm_contig_launder(int queue)
+vm_contig_launder(int queue, vm_paddr_t low, vm_paddr_t high)
 {
 	vm_page_t m, next;
+	vm_paddr_t pa;
 	int error;
 
 	TAILQ_FOREACH_SAFE(m, &vm_page_queues[queue].pl, pageq, next) {
@@ -168,6 +167,10 @@ vm_contig_launder(int queue)
 		if ((m->flags & PG_MARKER) != 0)
 			continue;
 
+		pa = VM_PAGE_TO_PHYS(m);
+		if (pa < low || pa + PAGE_SIZE > high)
+			continue;
+
 		if (!vm_pageout_page_lock(m, &next)) {
 			vm_page_unlock(m);
 			continue;
@@ -203,8 +206,8 @@ vm_page_release_contig(vm_page_t m, vm_p
 /*
  * Increase the number of cached pages.
  */
-static void
-vm_contig_grow_cache(int tries)
+void
+vm_contig_grow_cache(int tries, vm_paddr_t low, vm_paddr_t high)
 {
 	int actl, actmax, inactl, inactmax;
 
@@ -214,11 +217,11 @@ vm_contig_grow_cache(int tries)
 	actl = 0;
 	actmax = tries < 2 ? 0 : cnt.v_active_count;
 again:
-	if (inactl < inactmax && vm_contig_launder(PQ_INACTIVE)) {
+	if (inactl < inactmax && vm_contig_launder(PQ_INACTIVE, low, high)) {
 		inactl++;
 		goto again;
 	}
-	if (actl < actmax && vm_contig_launder(PQ_ACTIVE)) {
+	if (actl < actmax && vm_contig_launder(PQ_ACTIVE, low, high)) {
 		actl++;
 		goto again;
 	}
@@ -261,7 +264,7 @@ retry:
 			if (tries < ((flags & M_NOWAIT) != 0 ? 1 : 3)) {
 				VM_OBJECT_UNLOCK(object);
 				vm_map_unlock(map);
-				vm_contig_grow_cache(tries);
+				vm_contig_grow_cache(tries, low, high);
 				vm_map_lock(map);
 				VM_OBJECT_LOCK(object);
 				goto retry;
@@ -368,7 +371,7 @@ retry:
 	pages = vm_phys_alloc_contig(npgs, low, high, alignment, boundary);
 	if (pages == NULL) {
 		if (tries < ((flags & M_NOWAIT) != 0 ? 1 : 3)) {
-			vm_contig_grow_cache(tries);
+			vm_contig_grow_cache(tries, low, high);
 			tries++;
 			goto retry;
 		}

Modified: head/sys/vm/vm_pageout.h
==============================================================================
--- head/sys/vm/vm_pageout.h	Thu Jun  3 21:12:51 2010	(r208793)
+++ head/sys/vm/vm_pageout.h	Fri Jun  4 06:35:36 2010	(r208794)
@@ -105,5 +105,6 @@ boolean_t vm_pageout_fallback_object_loc
 int vm_pageout_flush(vm_page_t *, int, int);
 void vm_pageout_oom(int shortage);
 boolean_t vm_pageout_page_lock(vm_page_t, vm_page_t *);
+void vm_contig_grow_cache(int, vm_paddr_t, vm_paddr_t);
 #endif
 #endif	/* _VM_VM_PAGEOUT_H_ */


More information about the svn-src-all mailing list