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)
This commit is contained in:
parent
152e4bab37
commit
e9a1a12ab4
@ -967,19 +967,23 @@ pmap_ptpgzone_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
|
||||
{
|
||||
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);
|
||||
|
@ -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_page_t *next)
|
||||
}
|
||||
|
||||
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_pindex_t count)
|
||||
/*
|
||||
* 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 @@ kmem_alloc_attr(vm_map_t map, vm_size_t size, int flags, vm_paddr_t low,
|
||||
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 @@ kmem_alloc_contig(vm_map_t map, vm_size_t size, int flags, vm_paddr_t low,
|
||||
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;
|
||||
}
|
||||
|
@ -105,5 +105,6 @@ boolean_t vm_pageout_fallback_object_lock(vm_page_t, vm_page_t *);
|
||||
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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user