Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/uvm Make the DMA memory allocators (uvm_pglistalloc())
details: https://anonhg.NetBSD.org/src/rev/ec217a278cf0
branches: trunk
changeset: 532989:ec217a278cf0
user: drochner <drochner%NetBSD.org@localhost>
date: Tue Jun 18 15:49:48 2002 +0000
description:
Make the DMA memory allocators (uvm_pglistalloc())
obey the preferences expressed by freelist assignment,
to avoid wasting valuable "low memory" to devices which
don't really need it.
comments:
-I'm not sure searching the physsegs within a freelist
beginning with the biggest is the right thing. This is
what the "memory steal" code in uvm_page.c does, so
keep it consistent.
-There seems to be some confusion whether the upper
address limit passed is inclusive or not. Stays on
the save side, possibly leaving one page out.
-The boundary/pagemask check can be simplified, also some
arguments passed are only used for diagnostic checks.
-Integration with UVM_PAGE_TRKOWN???
diffstat:
sys/uvm/uvm_pglist.c | 190 ++++++++++++++++++++++++++++++++++++--------------
1 files changed, 137 insertions(+), 53 deletions(-)
diffs (289 lines):
diff -r 8ca38ae52cd8 -r ec217a278cf0 sys/uvm/uvm_pglist.c
--- a/sys/uvm/uvm_pglist.c Tue Jun 18 14:35:38 2002 +0000
+++ b/sys/uvm/uvm_pglist.c Tue Jun 18 15:49:48 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_pglist.c,v 1.21 2002/06/02 14:44:46 drochner Exp $ */
+/* $NetBSD: uvm_pglist.c,v 1.22 2002/06/18 15:49:48 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.21 2002/06/02 14:44:46 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.22 2002/06/18 15:49:48 drochner Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -85,8 +85,12 @@
*/
static void uvm_pglist_add(struct vm_page *, struct pglist *);
+static int uvm_pglistalloc_c_ps(int, psize_t, 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,
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,
struct pglist *, int);
@@ -132,61 +136,56 @@
}
static int
-uvm_pglistalloc_contig(size, low, high, alignment, boundary, rlist)
+uvm_pglistalloc_c_ps(psi, size, low, high, alignment, boundary, rlist)
+ int psi;
psize_t size;
paddr_t low, high, alignment, boundary;
struct pglist *rlist;
{
- paddr_t try, idxpa, lastidxpa;
- int psi;
+ int try, limit, tryidx, end, idx;
struct vm_page *pgs;
- int s, tryidx, idx, end, error;
+ paddr_t idxpa, lastidxpa;
u_long pagemask;
+#ifdef DEBUG
+ int cidx;
+#endif
- if (boundary != 0 && boundary < size)
- return (EINVAL);
+ limit = min(atop(high), vm_physmem[psi].avail_end);
pagemask = ~(boundary - 1);
- /* Default to "lose". */
- error = ENOMEM;
-
- /*
- * Block all memory allocation and lock the free list.
- */
-
- s = uvm_lock_fpageq();
-
- /* Are there even any free pages? */
- if (uvmexp.free <= (uvmexp.reserve_pagedaemon + uvmexp.reserve_kernel))
- goto out;
-
- for (try = low;; try += alignment) {
- if (try + size > high) {
+ for (try = roundup(max(atop(low), vm_physmem[psi].avail_start),
+ atop(alignment));; try += atop(alignment)) {
+ if (try + atop(size) >= limit) {
/*
* We've run past the allowable range.
*/
- goto out;
+ return (0); /* FAIL */
}
-
+#ifdef DEBUG
/*
* Make sure this is a managed physical page.
*/
- if ((psi = vm_physseg_find(atop(try), &idx)) == -1)
- continue; /* managed? */
- if (vm_physseg_find(atop(try + size), NULL) != psi)
- continue; /* end must be in this segment */
- tryidx = idx;
- end = idx + (size / PAGE_SIZE);
+ if (vm_physseg_find(try, &cidx) != psi)
+ panic("pgalloc contig: botch1");
+ if (cidx != try - vm_physmem[psi].start)
+ panic("pgalloc contig: botch2");
+ if (vm_physseg_find(try + atop(size), &cidx) != psi)
+ panic("pgalloc contig: botch3");
+ if (cidx != try - vm_physmem[psi].start + atop(size))
+ panic("pgalloc contig: botch4");
+#endif
+ tryidx = try - vm_physmem[psi].start;
+ end = tryidx + (size / PAGE_SIZE);
pgs = vm_physmem[psi].pgs;
/*
* Found a suitable starting page. See of the range is free.
*/
- for (; idx < end; idx++) {
+ for (idx = tryidx; idx < end; idx++) {
if (VM_PAGE_IS_FREE(&pgs[idx]) == 0) {
break;
}
@@ -199,7 +198,7 @@
* Region not contiguous.
*/
- break;
+ panic("pgalloc contig: botch5");
}
if (boundary != 0 &&
((lastidxpa ^ idxpa) & pagemask) != 0) {
@@ -224,7 +223,56 @@
while (idx < end) {
uvm_pglist_add(&pgs[idx++], rlist);
}
- error = 0;
+ return (1);
+}
+
+static int
+uvm_pglistalloc_contig(size, low, high, alignment, boundary, rlist)
+ psize_t size;
+ paddr_t low, high, alignment, boundary;
+ struct pglist *rlist;
+{
+ int fl, psi;
+ 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? */
+ if (uvmexp.free <= (uvmexp.reserve_pagedaemon + uvmexp.reserve_kernel))
+ goto out;
+
+ for (fl = 0; fl < VM_NFREELIST; fl++) {
+#if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST)
+ for (psi = vm_nphysseg - 1 ; psi >= 0 ; psi--)
+#else
+ for (psi = 0 ; psi < vm_nphysseg ; psi++)
+#endif
+ {
+ if (vm_physmem[psi].free_list != fl)
+ continue;
+
+ if (uvm_pglistalloc_c_ps(psi, size, low, high,
+ alignment, boundary, rlist)) {
+#if 0
+ printf("pgalloc: %lx-%lx\n",
+ TAILQ_FIRST(rlist)->phys_addr,
+ TAILQ_LAST(rlist, pglist)->phys_addr);
+#endif
+ error = 0;
+ goto out;
+ }
+ }
+ }
out:
/*
@@ -237,6 +285,39 @@
return (error);
}
+static void
+uvm_pglistalloc_s_ps(psi, low, high, rlist, todo)
+ int psi;
+ paddr_t low, high;
+ struct pglist *rlist;
+ int *todo;
+{
+ int limit, try;
+ struct vm_page *pg;
+#ifdef DEBUG
+ int cidx;
+#endif
+
+ limit = min(atop(high), vm_physmem[psi].avail_end);
+
+ for (try = max(atop(low), vm_physmem[psi].avail_start);
+ try < limit; try ++) {
+#ifdef DEBUG
+ if (vm_physseg_find(try, &cidx) != psi)
+ panic("pgalloc simple: botch1");
+ if (cidx != (try - vm_physmem[psi].start))
+ panic("pgalloc simple: botch2");
+#endif
+ pg = &vm_physmem[psi].pgs[try - vm_physmem[psi].start];
+ if (VM_PAGE_IS_FREE(pg) == 0)
+ continue;
+
+ uvm_pglist_add(pg, rlist);
+ if (--(*todo) == 0)
+ break;
+ }
+}
+
static int
uvm_pglistalloc_simple(size, low, high, rlist, waitok)
psize_t size;
@@ -244,10 +325,7 @@
struct pglist *rlist;
int waitok;
{
- psize_t try;
- int psi;
- struct vm_page *pg;
- int s, todo, idx, error;
+ int fl, psi, s, todo, error;
/* Default to "lose". */
error = ENOMEM;
@@ -265,23 +343,23 @@
if (uvmexp.free <= (uvmexp.reserve_pagedaemon + uvmexp.reserve_kernel))
goto out;
- for (try = low; try < high; try += PAGE_SIZE) {
-
- /*
- * Make sure this is a managed physical page.
- */
+ for (fl = 0; fl < VM_NFREELIST; fl++) {
+#if (VM_PHYSSEG_STRAT == VM_PSTRAT_BIGFIRST)
+ for (psi = vm_nphysseg - 1 ; psi >= 0 ; psi--)
+#else
+ for (psi = 0 ; psi < vm_nphysseg ; psi++)
+#endif
+ {
+ if (vm_physmem[psi].free_list != fl)
+ continue;
- if ((psi = vm_physseg_find(atop(try), &idx)) == -1)
- continue; /* managed? */
- pg = &vm_physmem[psi].pgs[idx];
- if (VM_PAGE_IS_FREE(pg) == 0)
- continue;
+ uvm_pglistalloc_s_ps(psi, low, high, rlist, &todo);
+ if (todo == 0) {
+ error = 0;
+ goto out;
+ }
+ }
- uvm_pglist_add(pg, rlist);
- if (--todo == 0) {
- error = 0;
- goto out;
- }
}
out:
@@ -303,6 +381,12 @@
} else
uvm_pglistfree(rlist);
}
+#if 0
+ if (!error)
+ printf("pgalloc: %lx..%lx\n",
+ TAILQ_FIRST(rlist)->phys_addr,
+ TAILQ_LAST(rlist, pglist)->phys_addr);
+#endif
return (error);
}
Home |
Main Index |
Thread Index |
Old Index