summaryrefslogtreecommitdiffstats
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.c233
1 files changed, 159 insertions, 74 deletions
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 1cd068e..ba5c985 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -61,7 +61,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
- * $Id: vm_object.c,v 1.39 1995/03/25 06:09:33 davidg Exp $
+ * $Id: vm_object.c,v 1.40 1995/03/25 08:42:14 davidg Exp $
*/
/*
@@ -86,6 +86,7 @@
static void _vm_object_allocate(vm_size_t, vm_object_t);
+
/*
* Virtual memory objects maintain the actual data
* associated with allocated virtual memory. A given
@@ -370,7 +371,6 @@ vm_object_terminate(object)
register vm_page_t p, next;
vm_object_t shadow_object;
int s;
- struct vnode *vp = NULL;
/*
* Detach the object from its shadow if we are the shadow's copy.
@@ -379,23 +379,12 @@ 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);
}
- if (object->pager && (object->pager->pg_type == PG_VNODE)) {
- vn_pager_t vnp = object->pager->pg_data;
- vp = vnp->vnp_vp;
- VOP_LOCK(vp);
- vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0);
- }
/*
- * Wait until the pageout daemon is through with the object.
+ * wait for the pageout daemon to be done with the object
*/
-
s = splhigh();
while (object->paging_in_progress) {
vm_object_unlock(object);
@@ -405,31 +394,6 @@ vm_object_terminate(object)
}
splx(s);
- /*
- * 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.
- *
- * 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 = next) {
- VM_PAGE_CHECK(p);
- next = p->listq.tqe_next;
-
- vm_page_lock_queues();
- if (p->flags & PG_CACHE)
- vm_page_free(p);
- else {
- s = splhigh();
- vm_page_unqueue(p);
- splx(s);
- }
- vm_page_unlock_queues();
- p = next;
- }
-
if (object->paging_in_progress != 0)
panic("vm_object_deallocate: pageout in progress");
@@ -437,11 +401,14 @@ vm_object_terminate(object)
* Clean and free the pages, as appropriate. All references to the
* object are gone, so we don't need to lock it.
*/
- if (vp != NULL) {
- VOP_UNLOCK(vp);
- vm_object_page_clean(object, 0, 0, TRUE);
+ if (object->pager && (object->pager->pg_type == PG_VNODE)) {
+ vn_pager_t vnp = object->pager->pg_data;
+ struct vnode *vp;
+
+ vp = vnp->vnp_vp;
VOP_LOCK(vp);
- vinvalbuf(vp, 0, NOCRED, NULL, 0, 0);
+ (void) _vm_object_page_clean(object, 0, 0, TRUE);
+ vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0);
VOP_UNLOCK(vp);
}
@@ -490,62 +457,180 @@ vm_object_terminate(object)
*
* The object must be locked.
*/
+
void
-vm_object_page_clean(object, start, end, syncio)
- register vm_object_t object;
- register vm_offset_t start;
- register vm_offset_t end;
+_vm_object_page_clean(object, start, end, syncio)
+ vm_object_t object;
+ vm_offset_t start;
+ vm_offset_t end;
boolean_t syncio;
{
- register vm_page_t p, nextp;
- int size;
- int s;
+ register vm_page_t p;
+ register vm_offset_t tstart, tend;
+ int pass;
+ int pgcount, s;
+ int allclean;
- if (object->pager == NULL)
+ if (object->pager == NULL || (object->flags & OBJ_WRITEABLE) == 0)
return;
if (start != end) {
start = trunc_page(start);
end = round_page(end);
}
- size = end - start;
-again:
+ object->flags &= ~OBJ_WRITEABLE;
+
+ pass = 0;
+startover:
+ tstart = start;
+ if (end == 0) {
+ tend = object->size;
+ } else {
+ tend = end;
+ }
/*
- * Wait until the pageout daemon is through with the object.
+ * Wait until potential collapse operation is complete
*/
- s = splhigh();
- while (object->paging_in_progress) {
- object->flags |= OBJ_PIPWNT;
- tsleep(object, PVM, "objpcw", 0);
+ if (object->flags & OBJ_INTERNAL) {
+ s = splhigh();
+ while (object->paging_in_progress) {
+ object->flags |= OBJ_PIPWNT;
+ tsleep(object, PVM, "objpcw", 0);
+ }
+ splx(s);
}
- splx(s);
- 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) || p->busy) {
- s = splhigh();
+ pgcount = object->resident_page_count;
- p->flags |= PG_WANTED;
- tsleep(p, PVM, "objpcn", 0);
- splx(s);
- goto again;
+ if (pass == 0 &&
+ (pgcount < 128 || pgcount > (object->size / (8 * PAGE_SIZE)))) {
+ allclean = 1;
+ for(; pgcount && (tstart < tend); tstart += PAGE_SIZE) {
+ p = vm_page_lookup(object, tstart);
+ if (!p)
+ continue;
+ --pgcount;
+ s = splhigh();
+ TAILQ_REMOVE(&object->memq, p, listq);
+ TAILQ_INSERT_TAIL(&object->memq, p, listq);
+ splx(s);
+ if ((p->flags & (PG_BUSY|PG_CACHE)) || p->busy || p->valid == 0 ||
+ p->bmapped) {
+ continue;
}
- size -= PAGE_SIZE;
-
vm_page_test_dirty(p);
+ if ((p->valid & p->dirty) != 0) {
+ vm_offset_t tincr;
+ tincr = vm_pageout_clean(p, VM_PAGEOUT_FORCE);
+ pgcount -= (tincr - 1);
+ tincr *= PAGE_SIZE;
+ tstart += tincr - PAGE_SIZE;
+ allclean = 0;
+ }
+ }
+ if (!allclean) {
+ pass = 1;
+ goto startover;
+ }
+ object->flags &= ~OBJ_WRITEABLE;
+ return;
+ }
+
+ allclean = 1;
+ while ((p = object->memq.tqh_first) != NULL && pgcount > 0) {
+
+ if (p->flags & PG_CACHE) {
+ goto donext;
+ }
- if ((p->dirty & p->valid) != 0) {
+ if (p->offset >= tstart && p->offset < tend) {
+ if (p->valid == 0 || p->bmapped) {
+ goto donext;
+ }
+
+ s = splhigh();
+ if ((p->flags & PG_BUSY) || p->busy) {
+ allclean = 0;
+ if (pass > 0) {
+ p->flags |= PG_WANTED;
+ tsleep(p, PVM, "objpcn", 0);
+ splx(s);
+ continue;
+ } else {
+ splx(s);
+ goto donext;
+ }
+ }
+
+ TAILQ_REMOVE(&object->memq, p, listq);
+ TAILQ_INSERT_TAIL(&object->memq, p, listq);
+ splx(s);
+
+ pgcount--;
+ vm_page_test_dirty(p);
+ if ((p->valid & p->dirty) != 0) {
vm_pageout_clean(p, VM_PAGEOUT_FORCE);
- goto again;
+ allclean = 0;
}
+ continue;
}
+ donext:
+ TAILQ_REMOVE(&object->memq, p, listq);
+ TAILQ_INSERT_TAIL(&object->memq, p, listq);
+ pgcount--;
+ }
+ if ((!allclean && (pass == 0)) || (object->flags & OBJ_WRITEABLE)) {
+ pass = 1;
+ object->flags &= ~OBJ_WRITEABLE;
+ goto startover;
}
return;
}
+
+void
+vm_object_page_clean(object, start, end, syncio)
+ register vm_object_t object;
+ register vm_offset_t start;
+ register vm_offset_t end;
+ boolean_t syncio;
+{
+ if (object->pager && (object->flags & OBJ_WRITEABLE) &&
+ (object->pager->pg_type == PG_VNODE)) {
+ vn_pager_t vnp = (vn_pager_t) object->pager->pg_data;
+ struct vnode *vp;
+
+ vp = vnp->vnp_vp;
+ vget(vp, 1);
+ _vm_object_page_clean(object, start, end, syncio);
+ vput(vp);
+ } else {
+ _vm_object_page_clean(object, start, end, syncio);
+ }
+}
+
+void
+vm_object_cache_clean()
+{
+ vm_object_t object;
+ vm_object_cache_lock();
+ while(1) {
+ object = vm_object_cached_list.tqh_first;
+ while( object) {
+ if( (object->flags & OBJ_WRITEABLE) &&
+ object->pager &&
+ object->pager->pg_type == PG_VNODE) {
+ vm_object_page_clean(object, 0, 0, 0);
+ goto loop;
+ }
+ object = object->cached_list.tqe_next;
+ }
+ return;
+loop:
+ }
+}
+
/*
* vm_object_deactivate_pages
*
@@ -1045,7 +1130,7 @@ vm_object_qcollapse(object)
next = p->listq.tqe_next;
if ((p->flags & (PG_BUSY | PG_FICTITIOUS | PG_CACHE)) ||
- !p->valid || p->hold_count || p->wire_count || p->busy || p->bmapped) {
+ !p->valid || p->hold_count || p->wire_count || p->busy) {
p = next;
continue;
}
OpenPOWER on IntegriCloud