summaryrefslogtreecommitdiffstats
path: root/sys/vm/vm_page.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm/vm_page.c')
-rw-r--r--sys/vm/vm_page.c113
1 files changed, 94 insertions, 19 deletions
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 23be218..e0cdd27 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.89 1998/01/31 20:30:18 dyson Exp $
+ * $Id: vm_page.c,v 1.90 1998/02/04 22:33:52 eivind Exp $
*/
/*
@@ -96,10 +96,10 @@ static vm_page_t vm_page_select_free __P((vm_object_t object,
* page structure.
*/
-static int vm_page_bucket_generation; /* generation id for buckets */
static struct pglist *vm_page_buckets; /* Array of buckets */
static int vm_page_bucket_count; /* How big is array? */
static int vm_page_hash_mask; /* Mask for hash function */
+static volatile int vm_page_bucket_generation;
struct pglist vm_page_queue_free[PQ_L2_SIZE] = {0};
struct pglist vm_page_queue_zero[PQ_L2_SIZE] = {0};
@@ -355,7 +355,6 @@ vm_page_startup(starta, enda, vaddr)
pa += PAGE_SIZE;
}
}
-
return (mapped);
}
@@ -391,8 +390,10 @@ vm_page_insert(m, object, pindex)
{
register struct pglist *bucket;
+#if !defined(MAX_PERF)
if (m->flags & PG_TABLED)
panic("vm_page_insert: already inserted");
+#endif
/*
* Record the object/offset pair in this page
@@ -446,13 +447,16 @@ vm_page_remove(m)
register vm_page_t m;
{
register struct pglist *bucket;
+ vm_object_t object;
if (!(m->flags & PG_TABLED))
return;
+#if !defined(MAX_PERF)
if ((m->flags & PG_BUSY) == 0) {
panic("vm_page_remove: page not busy");
}
+#endif
m->flags &= ~PG_BUSY;
if (m->flags & PG_WANTED) {
@@ -460,14 +464,15 @@ vm_page_remove(m)
wakeup(m);
}
- if (m->object->page_hint == m)
- m->object->page_hint = NULL;
+ object = m->object;
+ if (object->page_hint == m)
+ object->page_hint = NULL;
if (m->wire_count)
- m->object->wire_count--;
+ object->wire_count--;
if ((m->queue - m->pc) == PQ_CACHE)
- m->object->cache_count--;
+ object->cache_count--;
/*
* Remove from the object_object/offset hash table
@@ -481,14 +486,15 @@ vm_page_remove(m)
* Now remove from the object's list of backed pages.
*/
- TAILQ_REMOVE(&m->object->memq, m, listq);
+ TAILQ_REMOVE(&object->memq, m, listq);
/*
* And show that the object has one fewer resident page.
*/
- m->object->resident_page_count--;
- m->object->generation++;
+ object->resident_page_count--;
+ object->generation++;
+ m->object = NULL;
m->flags &= ~PG_TABLED;
}
@@ -509,25 +515,30 @@ vm_page_lookup(object, pindex)
{
register vm_page_t m;
register struct pglist *bucket;
- int curgeneration;
+ int generation;
int s;
/*
* Search the hash table for this object/offset pair
*/
- bucket = &vm_page_buckets[vm_page_hash(object, pindex)];
+ if (object->page_hint && (object->page_hint->pindex == pindex) &&
+ (object->page_hint->object == object))
+ return object->page_hint;
-restart:
- curgeneration = vm_page_bucket_generation;
+retry:
+ generation = vm_page_bucket_generation;
+ bucket = &vm_page_buckets[vm_page_hash(object, pindex)];
for (m = TAILQ_FIRST(bucket); m != NULL; m = TAILQ_NEXT(m,hashq)) {
- if (curgeneration != vm_page_bucket_generation)
- goto restart;
if ((m->object == object) && (m->pindex == pindex)) {
+ if (vm_page_bucket_generation != generation)
+ goto retry;
m->object->page_hint = m;
return (m);
}
}
+ if (vm_page_bucket_generation != generation)
+ goto retry;
return (NULL);
}
@@ -569,7 +580,8 @@ vm_page_unqueue_nowakeup(m)
(*pq->cnt)--;
(*pq->lcnt)--;
if ((queue - m->pc) == PQ_CACHE) {
- m->object->cache_count--;
+ if (m->object)
+ m->object->cache_count--;
}
}
}
@@ -593,7 +605,8 @@ vm_page_unqueue(m)
if ((cnt.v_cache_count + cnt.v_free_count) <
(cnt.v_free_reserved + cnt.v_cache_min))
pagedaemon_wakeup();
- m->object->cache_count--;
+ if (m->object)
+ m->object->cache_count--;
}
}
}
@@ -890,7 +903,10 @@ vm_page_alloc(object, pindex, page_req)
break;
default:
+ m = NULL;
+#if !defined(MAX_PERF)
panic("vm_page_alloc: invalid allocation class");
+#endif
}
queue = m->queue;
@@ -1045,12 +1061,15 @@ vm_page_freechk_and_unqueue(m)
}
if (m->wire_count != 0) {
+#if !defined(MAX_PERF)
if (m->wire_count > 1) {
panic("vm_page_free: invalid wire count (%d), pindex: 0x%x",
m->wire_count, m->pindex);
}
+#endif
m->wire_count = 0;
- m->object->wire_count--;
+ if (m->object)
+ m->object->wire_count--;
cnt.v_wire_count--;
}
@@ -1223,7 +1242,9 @@ vm_page_unwire(m)
cnt.v_active_count++;
}
} else {
+#if !defined(MAX_PERF)
panic("vm_page_unwire: invalid wire count: %d\n", m->wire_count);
+#endif
}
splx(s);
}
@@ -1278,17 +1299,21 @@ vm_page_cache(m)
{
int s;
+#if !defined(MAX_PERF)
if ((m->flags & PG_BUSY) || m->busy || m->wire_count) {
printf("vm_page_cache: attempting to cache busy page\n");
return;
}
+#endif
if ((m->queue - m->pc) == PQ_CACHE)
return;
vm_page_protect(m, VM_PROT_NONE);
+#if !defined(MAX_PERF)
if (m->dirty != 0) {
panic("vm_page_cache: caching a dirty page, pindex: %d", m->pindex);
}
+#endif
s = splvm();
vm_page_unqueue_nowakeup(m);
m->queue = PQ_CACHE + m->pc;
@@ -1300,6 +1325,54 @@ vm_page_cache(m)
splx(s);
}
+/*
+ * Grab a page, waiting until we are waken up due to the page
+ * changing state. We keep on waiting, if the page continues
+ * to be in the object. If the page doesn't exist, allocate it.
+ */
+vm_page_t
+vm_page_grab(object, pindex, allocflags)
+ vm_object_t object;
+ vm_pindex_t pindex;
+ int allocflags;
+{
+
+ vm_page_t m;
+ int s, generation;
+
+retrylookup:
+ if ((m = vm_page_lookup(object, pindex)) != NULL) {
+ if (m->busy || (m->flags & PG_BUSY)) {
+ generation = object->generation;
+
+ s = splvm();
+ while ((object->generation == generation) &&
+ (m->busy || (m->flags & PG_BUSY))) {
+ m->flags |= PG_WANTED | PG_REFERENCED;
+ tsleep(m, PVM, "pgrbwt", 0);
+ if ((allocflags & VM_ALLOC_RETRY) == 0) {
+ splx(s);
+ return NULL;
+ }
+ }
+ splx(s);
+ goto retrylookup;
+ } else {
+ m->flags |= PG_BUSY;
+ return m;
+ }
+ }
+
+ m = vm_page_alloc(object, pindex, allocflags & ~VM_ALLOC_RETRY);
+ if (m == NULL) {
+ VM_WAIT;
+ if ((allocflags & VM_ALLOC_RETRY) == 0)
+ return NULL;
+ goto retrylookup;
+ }
+
+ return m;
+}
/*
* mapping function for valid bits or for dirty bits in
@@ -1400,12 +1473,14 @@ contigmalloc1(size, type, flags, low, high, alignment, boundary, map)
vm_page_t pga = vm_page_array;
size = round_page(size);
+#if !defined(MAX_PERF)
if (size == 0)
panic("contigmalloc1: size must not be 0");
if ((alignment & (alignment - 1)) != 0)
panic("contigmalloc1: alignment must be a power of 2");
if ((boundary & (boundary - 1)) != 0)
panic("contigmalloc1: boundary must be a power of 2");
+#endif
start = 0;
for (pass = 0; pass <= 1; pass++) {
OpenPOWER on IntegriCloud