summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1997-11-06 08:35:50 +0000
committerdyson <dyson@FreeBSD.org>1997-11-06 08:35:50 +0000
commitbae55d266145fe1abe52e42bf49b39ad93844ad4 (patch)
tree586f852ac745d712b3524f1b95fc5a8771bc77df
parent7fafb4ffea7ff452f1df38e2b778f92a182e2a06 (diff)
downloadFreeBSD-src-bae55d266145fe1abe52e42bf49b39ad93844ad4.zip
FreeBSD-src-bae55d266145fe1abe52e42bf49b39ad93844ad4.tar.gz
Fix the "missing page" problem. Also, improve the performance of page
allocation in common cases.
-rw-r--r--sys/vm/vm_page.c107
1 files changed, 74 insertions, 33 deletions
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 18b4518..5571b70 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)vm_page.c 7.4 (Berkeley) 5/7/91
- * $Id: vm_page.c,v 1.81 1997/09/13 15:04:52 peter Exp $
+ * $Id: vm_page.c,v 1.82 1997/10/10 18:18:47 phk Exp $
*/
/*
@@ -574,22 +574,41 @@ vm_page_list_find(basequeue, index)
int i,j;
vm_page_t m;
int hindex;
+ struct vpgqueues *pq;
+
+ pq = &vm_page_queues[basequeue];
+
+ m = TAILQ_FIRST(pq[index].pl);
+ if (m)
+ return m;
for(j = 0; j < PQ_L1_SIZE; j++) {
- for(i = (PQ_L2_SIZE/2) - (PQ_L1_SIZE - 1);
- i >= 0;
+ int ij;
+ for(i = (PQ_L2_SIZE / 2) - PQ_L1_SIZE;
+ (ij = i + j) > 0;
i -= PQ_L1_SIZE) {
- hindex = (index + (i+j)) & PQ_L2_MASK;
- m = TAILQ_FIRST(vm_page_queues[basequeue + hindex].pl);
- if (m)
+
+ hindex = index + ij;
+ if (hindex >= PQ_L2_SIZE)
+ hindex -= PQ_L2_SIZE;
+ if (m = TAILQ_FIRST(pq[hindex].pl))
return m;
- hindex = (index - (i+j)) & PQ_L2_MASK;
- m = TAILQ_FIRST(vm_page_queues[basequeue + hindex].pl);
- if (m)
+ hindex = index - ij;
+ if (hindex < 0)
+ hindex += PQ_L2_SIZE;
+ if (m = TAILQ_FIRST(pq[hindex].pl))
return m;
}
}
+
+ hindex = index + PQ_L2_SIZE / 2;
+ if (hindex >= PQ_L2_SIZE)
+ hindex -= PQ_L2_SIZE;
+ m = TAILQ_FIRST(pq[hindex].pl);
+ if (m)
+ return m;
+
return NULL;
#else
return TAILQ_FIRST(vm_page_queues[basequeue].pl);
@@ -631,59 +650,81 @@ vm_page_select_free(object, pindex, prefqueue)
int i,j;
int index, hindex;
#endif
- vm_page_t m;
+ vm_page_t m, mh;
int oqueuediff;
+ struct vpgqueues *pq;
if (prefqueue == PQ_ZERO)
oqueuediff = PQ_FREE - PQ_ZERO;
else
oqueuediff = PQ_ZERO - PQ_FREE;
- if (object->page_hint) {
- if (object->page_hint->pindex == (pindex - 1)) {
- vm_offset_t last_phys;
- if ((object->page_hint->flags & PG_FICTITIOUS) == 0) {
- if ((object->page_hint < &vm_page_array[cnt.v_page_count-1]) &&
- (object->page_hint >= &vm_page_array[0])) {
+ if (mh = object->page_hint) {
+ if (mh->pindex == (pindex - 1)) {
+ if ((mh->flags & PG_FICTITIOUS) == 0) {
+ if ((mh < &vm_page_array[cnt.v_page_count-1]) &&
+ (mh >= &vm_page_array[0])) {
int queue;
- last_phys = VM_PAGE_TO_PHYS(object->page_hint);
- m = PHYS_TO_VM_PAGE(last_phys + PAGE_SIZE);
- queue = m->queue - m->pc;
- if (queue == PQ_FREE || queue == PQ_ZERO) {
- return m;
+ m = mh + 1;
+ if (VM_PAGE_TO_PHYS(m) == (VM_PAGE_TO_PHYS(mh) + PAGE_SIZE)) {
+ queue = m->queue - m->pc;
+ if (queue == PQ_FREE || queue == PQ_ZERO) {
+ return m;
+ }
}
}
}
}
}
-
+
+ pq = &vm_page_queues[prefqueue];
#if PQ_L2_SIZE > 1
- index = pindex + object->pg_color;
+ index = (pindex + object->pg_color) & PQ_L2_MASK;
+
+ if (m = TAILQ_FIRST(pq[index].pl))
+ return m;
+ if (m = TAILQ_FIRST(pq[index + oqueuediff].pl))
+ return m;
+
for(j = 0; j < PQ_L1_SIZE; j++) {
- for(i = (PQ_L2_SIZE/2) - (PQ_L1_SIZE - 1);
- (i + j) >= 0;
+ int ij;
+ for(i = (PQ_L2_SIZE / 2) - PQ_L1_SIZE;
+ (ij = i + j) >= 0;
i -= PQ_L1_SIZE) {
- hindex = prefqueue + ((index + (i+j)) & PQ_L2_MASK);
- if (m = TAILQ_FIRST(vm_page_queues[hindex].pl))
+ hindex = index + ij;
+ if (hindex >= PQ_L2_SIZE)
+ hindex -= PQ_L2_SIZE;
+ if (m = TAILQ_FIRST(pq[hindex].pl))
return m;
- if (m = TAILQ_FIRST(vm_page_queues[hindex + oqueuediff].pl))
+ if (m = TAILQ_FIRST(pq[hindex + oqueuediff].pl))
return m;
- hindex = prefqueue + ((index - (i+j)) & PQ_L2_MASK);
- if (m = TAILQ_FIRST(vm_page_queues[hindex].pl))
+ hindex = index - ij;
+ if (hindex < 0)
+ hindex += PQ_L2_SIZE;
+ if (m = TAILQ_FIRST(pq[hindex].pl))
return m;
- if (m = TAILQ_FIRST(vm_page_queues[hindex + oqueuediff].pl))
+ if (m = TAILQ_FIRST(pq[hindex + oqueuediff].pl))
return m;
}
}
+
+ hindex = index + PQ_L2_SIZE / 2;
+ if (hindex >= PQ_L2_SIZE)
+ hindex -= PQ_L2_SIZE;
+ if (m = TAILQ_FIRST(pq[hindex].pl))
+ return m;
+ if (m = TAILQ_FIRST(pq[hindex+oqueuediff].pl))
+ return m;
+
#else
- if (m = TAILQ_FIRST(vm_page_queues[prefqueue].pl))
+ if (m = TAILQ_FIRST(pq[0].pl))
return m;
else
- return TAILQ_FIRST(vm_page_queues[prefqueue + oqueuediff].pl);
+ return TAILQ_FIRST(pq[oqueuediff].pl);
#endif
return NULL;
OpenPOWER on IntegriCloud