summaryrefslogtreecommitdiff
path: root/sys/vm/vm_object.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm/vm_object.c')
-rw-r--r--sys/vm/vm_object.c495
1 files changed, 352 insertions, 143 deletions
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index d11fa8be014f..a6419dc22aa8 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -72,6 +72,12 @@
#include <vm/vm.h>
#include <vm/vm_page.h>
+#include <vm/vm_pageout.h>
+
+static void _vm_object_allocate(vm_size_t, vm_object_t);
+void vm_object_deactivate_pages(vm_object_t);
+void vm_object_cache_trim(void);
+void vm_object_remove(vm_pager_t);
/*
* Virtual memory objects maintain the actual data
@@ -99,26 +105,56 @@
*
*/
+
struct vm_object kernel_object_store;
struct vm_object kmem_object_store;
+extern int vm_cache_max;
#define VM_OBJECT_HASH_COUNT 157
-int vm_cache_max = 100; /* can patch if necessary */
-struct vm_object_hash_head vm_object_hashtable[VM_OBJECT_HASH_COUNT];
+struct vm_object_hash_head vm_object_hashtable[VM_OBJECT_HASH_COUNT];
long object_collapses = 0;
long object_bypasses = 0;
-static void _vm_object_allocate __P((vm_size_t, vm_object_t));
+static void
+_vm_object_allocate(size, object)
+ vm_size_t size;
+ register vm_object_t object;
+{
+ bzero(object, sizeof *object);
+ TAILQ_INIT(&object->memq);
+ vm_object_lock_init(object);
+ object->ref_count = 1;
+ object->resident_page_count = 0;
+ object->size = size;
+ object->flags = OBJ_INTERNAL; /* vm_allocate_with_pager will reset */
+ object->paging_in_progress = 0;
+ object->copy = NULL;
+
+ /*
+ * Object starts out read-write, with no pager.
+ */
+
+ object->pager = NULL;
+ object->paging_offset = 0;
+ object->shadow = NULL;
+ object->shadow_offset = (vm_offset_t) 0;
+
+ simple_lock(&vm_object_list_lock);
+ TAILQ_INSERT_TAIL(&vm_object_list, object, object_list);
+ vm_object_count++;
+ cnt.v_nzfod += atop(size);
+ simple_unlock(&vm_object_list_lock);
+}
/*
* vm_object_init:
*
* Initialize the VM objects module.
*/
-void vm_object_init(size)
- vm_size_t size;
+void
+vm_object_init(vm_offset_t nothing)
{
register int i;
@@ -132,10 +168,12 @@ void vm_object_init(size)
TAILQ_INIT(&vm_object_hashtable[i]);
kernel_object = &kernel_object_store;
- _vm_object_allocate(size, kernel_object);
+ _vm_object_allocate(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS,
+ kernel_object);
kmem_object = &kmem_object_store;
- _vm_object_allocate(VM_KMEM_SIZE + VM_MBUF_SIZE, kmem_object);
+ _vm_object_allocate(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS,
+ kmem_object);
}
/*
@@ -144,55 +182,30 @@ void vm_object_init(size)
* Returns a new object with the given size.
*/
-vm_object_t vm_object_allocate(size)
+vm_object_t
+vm_object_allocate(size)
vm_size_t size;
{
register vm_object_t result;
+ int s;
result = (vm_object_t)
malloc((u_long)sizeof *result, M_VMOBJ, M_WAITOK);
+
_vm_object_allocate(size, result);
return(result);
}
-static void
-_vm_object_allocate(size, object)
- vm_size_t size;
- register vm_object_t object;
-{
- TAILQ_INIT(&object->memq);
- vm_object_lock_init(object);
- object->ref_count = 1;
- object->resident_page_count = 0;
- object->size = size;
- object->flags = OBJ_INTERNAL; /* vm_allocate_with_pager will reset */
- object->paging_in_progress = 0;
- object->copy = NULL;
-
- /*
- * Object starts out read-write, with no pager.
- */
-
- object->pager = NULL;
- object->paging_offset = 0;
- object->shadow = NULL;
- object->shadow_offset = (vm_offset_t) 0;
-
- simple_lock(&vm_object_list_lock);
- TAILQ_INSERT_TAIL(&vm_object_list, object, object_list);
- vm_object_count++;
- cnt.v_nzfod += atop(size);
- simple_unlock(&vm_object_list_lock);
-}
/*
* vm_object_reference:
*
* Gets another reference to the given object.
*/
-void vm_object_reference(object)
+inline void
+vm_object_reference(object)
register vm_object_t object;
{
if (object == NULL)
@@ -214,8 +227,9 @@ void vm_object_reference(object)
*
* No object may be locked.
*/
-void vm_object_deallocate(object)
- register vm_object_t object;
+void
+vm_object_deallocate(object)
+ vm_object_t object;
{
vm_object_t temp;
@@ -235,11 +249,11 @@ void vm_object_deallocate(object)
vm_object_lock(object);
if (--(object->ref_count) != 0) {
+ vm_object_unlock(object);
/*
* If there are still references, then
* we are done.
*/
- vm_object_unlock(object);
vm_object_cache_unlock();
return;
}
@@ -257,7 +271,12 @@ void vm_object_deallocate(object)
vm_object_cached++;
vm_object_cache_unlock();
- vm_object_deactivate_pages(object);
+/*
+ * this code segment was removed because it kills performance with
+ * large -- repetively used binaries. The functionality now resides
+ * in the pageout daemon
+ * vm_object_deactivate_pages(object);
+ */
vm_object_unlock(object);
vm_object_cache_trim();
@@ -269,7 +288,7 @@ void vm_object_deallocate(object)
*/
vm_object_remove(object->pager);
vm_object_cache_unlock();
-
+
temp = object->shadow;
vm_object_terminate(object);
/* unlocks and deallocates object */
@@ -277,18 +296,19 @@ void vm_object_deallocate(object)
}
}
-
/*
* vm_object_terminate actually destroys the specified object, freeing
* up all previously used resources.
*
* The object must be locked.
*/
-void vm_object_terminate(object)
+void
+vm_object_terminate(object)
register vm_object_t object;
{
register vm_page_t p;
vm_object_t shadow_object;
+ int s;
/*
* Detach the object from its shadow if we are the shadow's
@@ -298,28 +318,68 @@ void vm_object_terminate(object)
vm_object_lock(shadow_object);
if (shadow_object->copy == object)
shadow_object->copy = NULL;
-#if 0
+/*
else if (shadow_object->copy != NULL)
panic("vm_object_terminate: copy/shadow inconsistency");
-#endif
+*/
vm_object_unlock(shadow_object);
}
/*
- * Wait until the pageout daemon is through with the object.
+ * Wait until the pageout daemon is through
+ * with the object.
*/
+
while (object->paging_in_progress) {
vm_object_sleep((int)object, object, FALSE);
vm_object_lock(object);
}
/*
- * If not an internal object clean all the pages, removing them
- * from paging queues as we go.
+ * While the paging system is locked,
+ * pull the object's pages off the active
+ * and inactive queues. This keeps the
+ * pageout daemon from playing with them
+ * during vm_pager_deallocate.
*
- * XXX need to do something in the event of a cleaning error.
+ * We can't free the pages yet, because the
+ * object's pager may have to write them out
+ * before deallocating the paging space.
+ */
+
+ for( p = object->memq.tqh_first; p; p=p->listq.tqe_next) {
+ VM_PAGE_CHECK(p);
+
+ vm_page_lock_queues();
+ s = splimp();
+ if (p->flags & PG_ACTIVE) {
+ TAILQ_REMOVE(&vm_page_queue_active, p, pageq);
+ p->flags &= ~PG_ACTIVE;
+ cnt.v_active_count--;
+ }
+
+ if (p->flags & PG_INACTIVE) {
+ TAILQ_REMOVE(&vm_page_queue_inactive, p, pageq);
+ p->flags &= ~PG_INACTIVE;
+ cnt.v_inactive_count--;
+ }
+ splx(s);
+ vm_page_unlock_queues();
+ }
+
+ vm_object_unlock(object);
+
+ if (object->paging_in_progress != 0)
+ panic("vm_object_deallocate: pageout in progress");
+
+ /*
+ * Clean and free the pages, as appropriate.
+ * All references to the object are gone,
+ * so we don't need to lock it.
*/
+
if ((object->flags & OBJ_INTERNAL) == 0) {
+ vm_object_lock(object);
(void) vm_object_page_clean(object, 0, 0, TRUE, TRUE);
vm_object_unlock(object);
}
@@ -335,23 +395,24 @@ void vm_object_terminate(object)
cnt.v_pfree++;
vm_page_unlock_queues();
}
- if ((object->flags & OBJ_INTERNAL) == 0)
- vm_object_unlock(object);
/*
- * Let the pager know object is dead.
+ * Let the pager know object is dead.
*/
+
if (object->pager != NULL)
vm_pager_deallocate(object->pager);
+
simple_lock(&vm_object_list_lock);
TAILQ_REMOVE(&vm_object_list, object, object_list);
vm_object_count--;
simple_unlock(&vm_object_list_lock);
/*
- * Free the space for the object.
+ * Free the space for the object.
*/
+
free((caddr_t)object, M_VMOBJ);
}
@@ -359,6 +420,69 @@ void vm_object_terminate(object)
* vm_object_page_clean
*
* Clean all dirty pages in the specified range of object.
+ * Leaves page on whatever queue it is currently on.
+ *
+ * Odd semantics: if start == end, we clean everything.
+ *
+ * The object must be locked.
+ */
+#if 1
+boolean_t
+vm_object_page_clean(object, start, end, syncio, de_queue)
+ register vm_object_t object;
+ register vm_offset_t start;
+ register vm_offset_t end;
+ boolean_t syncio;
+ boolean_t de_queue;
+{
+ register vm_page_t p, nextp;
+ int s;
+ int size;
+
+ if (object->pager == NULL)
+ return 1;
+
+ if (start != end) {
+ start = trunc_page(start);
+ end = round_page(end);
+ }
+ size = end - start;
+
+again:
+ /*
+ * Wait until the pageout daemon is through with the object.
+ */
+ while (object->paging_in_progress) {
+ vm_object_sleep((int)object, object, FALSE);
+ }
+
+ nextp = object->memq.tqh_first;
+ while ( (p = nextp) && ((start == end) || (size != 0) ) ) {
+ nextp = p->listq.tqe_next;
+ if (start == end || (p->offset >= start && p->offset < end)) {
+ if (p->flags & PG_BUSY)
+ continue;
+
+ size -= PAGE_SIZE;
+
+ if ((p->flags & PG_CLEAN)
+ && pmap_is_modified(VM_PAGE_TO_PHYS(p)))
+ p->flags &= ~PG_CLEAN;
+
+ if ((p->flags & PG_CLEAN) == 0) {
+ vm_pageout_clean(p,VM_PAGEOUT_FORCE);
+ goto again;
+ }
+ }
+ }
+ wakeup((caddr_t)object);
+ return 1;
+}
+#endif
+/*
+ * vm_object_page_clean
+ *
+ * Clean all dirty pages in the specified range of object.
* If syncio is TRUE, page cleaning is done synchronously.
* If de_queue is TRUE, pages are removed from any paging queue
* they were on, otherwise they are left on whatever queue they
@@ -372,6 +496,7 @@ void vm_object_terminate(object)
* somewhere. We attempt to clean (and dequeue) all pages regardless
* of where an error occurs.
*/
+#if 0
boolean_t
vm_object_page_clean(object, start, end, syncio, de_queue)
register vm_object_t object;
@@ -421,6 +546,7 @@ again:
* Loop through the object page list cleaning as necessary.
*/
for (p = object->memq.tqh_first; p != NULL; p = p->listq.tqe_next) {
+ onqueue = 0;
if ((start == end || p->offset >= start && p->offset < end) &&
!(p->flags & PG_FICTITIOUS)) {
if ((p->flags & PG_CLEAN) &&
@@ -493,6 +619,7 @@ again:
}
return (noerror);
}
+#endif
/*
* vm_object_deactivate_pages
@@ -539,6 +666,7 @@ vm_object_cache_trim()
vm_object_cache_unlock();
}
+
/*
* vm_object_pmap_copy:
*
@@ -576,7 +704,8 @@ void vm_object_pmap_copy(object, start, end)
*
* The object must *not* be locked.
*/
-void vm_object_pmap_remove(object, start, end)
+void
+vm_object_pmap_remove(object, start, end)
register vm_object_t object;
register vm_offset_t start;
register vm_offset_t end;
@@ -587,9 +716,19 @@ void vm_object_pmap_remove(object, start, end)
return;
vm_object_lock(object);
- for (p = object->memq.tqh_first; p != NULL; p = p->listq.tqe_next)
- if ((start <= p->offset) && (p->offset < end))
+again:
+ for (p = object->memq.tqh_first; p != NULL; p = p->listq.tqe_next) {
+ if ((start <= p->offset) && (p->offset < end)) {
+ if (p->flags & PG_BUSY) {
+ p->flags |= PG_WANTED;
+ tsleep((caddr_t) p, PVM, "vmopmr", 0);
+ goto again;
+ }
pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_NONE);
+ if ((p->flags & PG_CLEAN) == 0)
+ p->flags |= PG_LAUNDRY;
+ }
+ }
vm_object_unlock(object);
}
@@ -629,6 +768,7 @@ void vm_object_copy(src_object, src_offset, size,
return;
}
+
/*
* If the object's pager is null_pager or the
* default pager, we don't have to make a copy
@@ -637,7 +777,15 @@ void vm_object_copy(src_object, src_offset, size,
*/
vm_object_lock(src_object);
+
+ /*
+ * Try to collapse the object before copying it.
+ */
+
+ vm_object_collapse(src_object);
+
if (src_object->pager == NULL ||
+ src_object->pager->pg_type == PG_SWAP ||
(src_object->flags & OBJ_INTERNAL)) {
/*
@@ -664,10 +812,6 @@ void vm_object_copy(src_object, src_offset, size,
return;
}
- /*
- * Try to collapse the object before copying it.
- */
- vm_object_collapse(src_object);
/*
* If the object has a pager, the pager wants to
@@ -798,7 +942,8 @@ void vm_object_copy(src_object, src_offset, size,
* are returned in the source parameters.
*/
-void vm_object_shadow(object, offset, length)
+void
+vm_object_shadow(object, offset, length)
vm_object_t *object; /* IN/OUT */
vm_offset_t *offset; /* IN/OUT */
vm_size_t length;
@@ -843,7 +988,8 @@ void vm_object_shadow(object, offset, length)
* Set the specified object's pager to the specified pager.
*/
-void vm_object_setpager(object, pager, paging_offset,
+void
+vm_object_setpager(object, pager, paging_offset,
read_only)
vm_object_t object;
vm_pager_t pager;
@@ -852,9 +998,12 @@ void vm_object_setpager(object, pager, paging_offset,
{
#ifdef lint
read_only++; /* No longer used */
-#endif
+#endif lint
vm_object_lock(object); /* XXX ? */
+ if (object->pager && object->pager != pager) {
+ panic("!!!pager already allocated!!!\n");
+ }
object->pager = pager;
object->paging_offset = paging_offset;
vm_object_unlock(object); /* XXX ? */
@@ -865,7 +1014,7 @@ void vm_object_setpager(object, pager, paging_offset,
*/
#define vm_object_hash(pager) \
- (((unsigned)pager)%VM_OBJECT_HASH_COUNT)
+ (((unsigned)pager >> 5)%VM_OBJECT_HASH_COUNT)
/*
* vm_object_lookup looks in the object cache for an object with the
@@ -965,38 +1114,6 @@ vm_object_remove(pager)
}
}
-/*
- * vm_object_cache_clear removes all objects from the cache.
- *
- */
-
-void vm_object_cache_clear()
-{
- register vm_object_t object;
-
- /*
- * Remove each object in the cache by scanning down the
- * list of cached objects.
- */
- vm_object_cache_lock();
- while ((object = vm_object_cached_list.tqh_first) != NULL) {
- vm_object_cache_unlock();
-
- /*
- * Note: it is important that we use vm_object_lookup
- * to gain a reference, and not vm_object_reference, because
- * the logic for removing an object from the cache lies in
- * lookup.
- */
- if (object != vm_object_lookup(object->pager))
- panic("vm_object_cache_clear: I'm sooo confused.");
- pager_cache(object, FALSE);
-
- vm_object_cache_lock();
- }
- vm_object_cache_unlock();
-}
-
boolean_t vm_object_collapse_allowed = TRUE;
/*
* vm_object_collapse:
@@ -1008,8 +1125,12 @@ boolean_t vm_object_collapse_allowed = TRUE;
* Requires that the object be locked and the page
* queues be unlocked.
*
+ * This routine has significant changes by John S. Dyson
+ * to fix some swap memory leaks. 18 Dec 93
+ *
*/
-void vm_object_collapse(object)
+void
+vm_object_collapse(object)
register vm_object_t object;
{
@@ -1027,11 +1148,10 @@ void vm_object_collapse(object)
* Verify that the conditions are right for collapse:
*
* The object exists and no pages in it are currently
- * being paged out (or have ever been paged out).
+ * being paged out.
*/
if (object == NULL ||
- object->paging_in_progress != 0 ||
- object->pager != NULL)
+ object->paging_in_progress != 0)
return;
/*
@@ -1067,12 +1187,24 @@ void vm_object_collapse(object)
* parent object.
*/
if (backing_object->shadow != NULL &&
- backing_object->shadow->copy != NULL) {
+ backing_object->shadow->copy == backing_object) {
vm_object_unlock(backing_object);
return;
}
/*
+ * we can deal only with the swap pager
+ */
+ if ((object->pager &&
+ object->pager->pg_type != PG_SWAP) ||
+ (backing_object->pager &&
+ backing_object->pager->pg_type != PG_SWAP)) {
+ vm_object_unlock(backing_object);
+ return;
+ }
+
+
+ /*
* We know that we can either collapse the backing
* object (if the parent is the only reference to
* it) or (perhaps) remove the parent's reference
@@ -1098,7 +1230,8 @@ void vm_object_collapse(object)
* pages that shadow them.
*/
- while ((p = backing_object->memq.tqh_first) != NULL) {
+ while (p = backing_object->memq.tqh_first) {
+
new_offset = (p->offset - backing_offset);
/*
@@ -1116,19 +1249,12 @@ void vm_object_collapse(object)
vm_page_unlock_queues();
} else {
pp = vm_page_lookup(object, new_offset);
- if (pp != NULL && !(pp->flags & PG_FAKE)) {
+ if (pp != NULL || (object->pager && vm_pager_has_page(object->pager,
+ object->paging_offset + new_offset))) {
vm_page_lock_queues();
vm_page_free(p);
vm_page_unlock_queues();
- }
- else {
- if (pp) {
- /* may be someone waiting for it */
- PAGE_WAKEUP(pp);
- vm_page_lock_queues();
- vm_page_free(pp);
- vm_page_unlock_queues();
- }
+ } else {
vm_page_rename(p, object, new_offset);
}
}
@@ -1136,19 +1262,50 @@ void vm_object_collapse(object)
/*
* Move the pager from backing_object to object.
- *
- * XXX We're only using part of the paging space
- * for keeps now... we ought to discard the
- * unused portion.
*/
if (backing_object->pager) {
- object->pager = backing_object->pager;
- object->paging_offset = backing_offset +
- backing_object->paging_offset;
- backing_object->pager = NULL;
+ backing_object->paging_in_progress++;
+ if (object->pager) {
+ vm_pager_t bopager;
+ object->paging_in_progress++;
+ /*
+ * copy shadow object pages into ours
+ * and destroy unneeded pages in shadow object.
+ */
+ bopager = backing_object->pager;
+ backing_object->pager = NULL;
+ vm_object_remove(backing_object->pager);
+ swap_pager_copy(
+ bopager, backing_object->paging_offset,
+ object->pager, object->paging_offset,
+ object->shadow_offset);
+ object->paging_in_progress--;
+ if (object->paging_in_progress == 0)
+ wakeup((caddr_t)object);
+ } else {
+ object->paging_in_progress++;
+ /*
+ * grab the shadow objects pager
+ */
+ object->pager = backing_object->pager;
+ object->paging_offset = backing_object->paging_offset + backing_offset;
+ vm_object_remove(backing_object->pager);
+ backing_object->pager = NULL;
+ /*
+ * free unnecessary blocks
+ */
+ swap_pager_freespace(object->pager, 0, object->paging_offset);
+ object->paging_in_progress--;
+ if (object->paging_in_progress == 0)
+ wakeup((caddr_t)object);
+ }
+ backing_object->paging_in_progress--;
+ if (backing_object->paging_in_progress == 0)
+ wakeup((caddr_t)backing_object);
}
+
/*
* Object now shadows whatever backing_object did.
* Note that the reference to backing_object->shadow
@@ -1173,7 +1330,7 @@ void vm_object_collapse(object)
simple_lock(&vm_object_list_lock);
TAILQ_REMOVE(&vm_object_list, backing_object,
- object_list);
+ object_list);
vm_object_count--;
simple_unlock(&vm_object_list_lock);
@@ -1204,9 +1361,7 @@ void vm_object_collapse(object)
* of pages here.
*/
- for (p = backing_object->memq.tqh_first;
- p != NULL;
- p = p->listq.tqe_next) {
+ for( p = backing_object->memq.tqh_first;p;p=p->listq.tqe_next) {
new_offset = (p->offset - backing_offset);
/*
@@ -1219,10 +1374,9 @@ void vm_object_collapse(object)
*/
if (p->offset >= backing_offset &&
- new_offset < size &&
- ((pp = vm_page_lookup(object, new_offset))
- == NULL ||
- (pp->flags & PG_FAKE))) {
+ new_offset <= size &&
+ ((pp = vm_page_lookup(object, new_offset)) == NULL || (pp->flags & PG_FAKE)) &&
+ (!object->pager || !vm_pager_has_page(object->pager, object->paging_offset+new_offset))) {
/*
* Page still needed.
* Can't go any further.
@@ -1239,23 +1393,24 @@ void vm_object_collapse(object)
* count is at least 2.
*/
- object->shadow = backing_object->shadow;
- vm_object_reference(object->shadow);
+ vm_object_reference(object->shadow = backing_object->shadow);
object->shadow_offset += backing_object->shadow_offset;
/*
- * Backing object might have had a copy pointer
- * to us. If it did, clear it.
+ * Backing object might have had a copy pointer
+ * to us. If it did, clear it.
*/
if (backing_object->copy == object) {
backing_object->copy = NULL;
}
-
+
/* Drop the reference count on backing_object.
* Since its ref_count was at least 2, it
* will not vanish; so we don't need to call
* vm_object_deallocate.
*/
+ if (backing_object->ref_count == 1)
+ printf("should have called obj deallocate\n");
backing_object->ref_count--;
vm_object_unlock(backing_object);
@@ -1277,23 +1432,55 @@ void vm_object_collapse(object)
*
* The object must be locked.
*/
-void vm_object_page_remove(object, start, end)
+void
+vm_object_page_remove(object, start, end)
register vm_object_t object;
register vm_offset_t start;
register vm_offset_t end;
{
register vm_page_t p, next;
+ vm_offset_t size;
+ int cnt;
+ int s;
if (object == NULL)
return;
- for (p = object->memq.tqh_first; p != NULL; p = next) {
- next = p->listq.tqe_next;
- if ((start <= p->offset) && (p->offset < end)) {
- pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_NONE);
- vm_page_lock_queues();
- vm_page_free(p);
- vm_page_unlock_queues();
+ start = trunc_page(start);
+ end = round_page(end);
+again:
+ size = end-start;
+ if (size > 4*PAGE_SIZE || size >= object->size/4) {
+ for (p = object->memq.tqh_first; (p != NULL && size > 0); p = next) {
+ next = p->listq.tqe_next;
+ if ((start <= p->offset) && (p->offset < end)) {
+ if (p->flags & PG_BUSY) {
+ p->flags |= PG_WANTED;
+ tsleep((caddr_t) p, PVM, "vmopar", 0);
+ goto again;
+ }
+ pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_NONE);
+ vm_page_lock_queues();
+ vm_page_free(p);
+ vm_page_unlock_queues();
+ size -= PAGE_SIZE;
+ }
+ }
+ } else {
+ while (size > 0) {
+ while (p = vm_page_lookup(object, start)) {
+ if (p->flags & PG_BUSY) {
+ p->flags |= PG_WANTED;
+ tsleep((caddr_t) p, PVM, "vmopar", 0);
+ goto again;
+ }
+ pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_NONE);
+ vm_page_lock_queues();
+ vm_page_free(p);
+ vm_page_unlock_queues();
+ }
+ start += PAGE_SIZE;
+ size -= PAGE_SIZE;
}
}
}
@@ -1389,6 +1576,27 @@ boolean_t vm_object_coalesce(prev_object, next_object,
}
/*
+ * returns page after looking up in shadow chain
+ */
+
+vm_page_t
+vm_object_page_lookup(object, offset)
+ vm_object_t object;
+ vm_offset_t offset;
+{
+ vm_page_t m;
+ if (!(m=vm_page_lookup(object, offset))) {
+ if (!object->shadow)
+ return 0;
+ else
+ return vm_object_page_lookup(object->shadow, offset + object->shadow_offset);
+ }
+ return m;
+}
+
+#define DEBUG
+#if defined(DEBUG) || (NDDB > 0)
+/*
* vm_object_print: [ debug ]
*/
void vm_object_print(object, full)
@@ -1434,3 +1642,4 @@ void vm_object_print(object, full)
printf("\n");
indent -= 2;
}
+#endif /* defined(DEBUG) || (NDDB > 0) */