diff options
Diffstat (limited to 'sys/vm/vm_object.c')
-rw-r--r-- | sys/vm/vm_object.c | 278 |
1 files changed, 170 insertions, 108 deletions
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index bbdb707..9d059e2 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.19 1995/01/24 10:13:14 davidg Exp $ + * $Id: vm_object.c,v 1.20 1995/01/25 20:36:29 davidg Exp $ */ /* @@ -82,9 +82,9 @@ #include <vm/vm_pager.h> #include <vm/swap_pager.h> #include <vm/vnode_pager.h> +#include <vm/vm_kern.h> static void _vm_object_allocate(vm_size_t, vm_object_t); -static void vm_object_rcollapse(vm_object_t, vm_object_t); /* * Virtual memory objects maintain the actual data @@ -130,26 +130,23 @@ _vm_object_allocate(size, object) vm_size_t size; register vm_object_t object; { - bzero(object, sizeof *object); TAILQ_INIT(&object->memq); TAILQ_INIT(&object->reverse_shadow_head); - vm_object_lock_init(object); - object->ref_count = 1; - object->resident_page_count = 0; + object->size = size; + object->ref_count = 1; + vm_object_lock_init(object); object->flags = OBJ_INTERNAL; /* vm_allocate_with_pager will reset */ object->paging_in_progress = 0; - object->copy = NULL; - object->last_read = 0; - - /* - * Object starts out read-write, with no pager. - */ + object->resident_page_count = 0; object->pager = NULL; object->paging_offset = 0; object->shadow = NULL; object->shadow_offset = (vm_offset_t) 0; + object->copy = NULL; + + object->last_read = 0; simple_lock(&vm_object_list_lock); TAILQ_INSERT_TAIL(&vm_object_list, object, object_list); @@ -258,13 +255,40 @@ vm_object_deallocate(object) vm_object_lock(object); if (--(object->ref_count) != 0) { if (object->ref_count == 1) { - if (object->reverse_shadow_head.tqh_first) { - ++object->reverse_shadow_head.tqh_first->ref_count; - if (vm_object_lock_try(object->reverse_shadow_head.tqh_first)) { - vm_object_rcollapse(object->reverse_shadow_head.tqh_first, object); - vm_object_unlock(object->reverse_shadow_head.tqh_first); + vm_object_t robject; + robject = object->reverse_shadow_head.tqh_first; + if( robject) { + int s; + robject->ref_count += 2; + object->ref_count += 1; + + do { + s = splhigh(); + while( robject->paging_in_progress) { + tsleep(robject, PVM, "objde1", 0); + } + + while( object->paging_in_progress) { + tsleep(object, PVM, "objde2", 0); + } + splx(s); + + } while( object->paging_in_progress || robject->paging_in_progress); + + object->ref_count -= 1; + robject->ref_count -= 2; + if( robject->ref_count == 0) { + vm_object_unlock(object); + vm_object_cache_unlock(); + robject->ref_count += 1; + vm_object_deallocate(robject); + return; } - vm_object_deallocate(object->reverse_shadow_head.tqh_first); + vm_object_cache_unlock(); + vm_object_unlock(object); + vm_object_lock(robject); + vm_object_collapse(robject); + return; } } vm_object_unlock(object); @@ -801,7 +825,6 @@ vm_object_copy(src_object, src_offset, size, vm_object_collapse(src_object); if (src_object->pager == NULL || - src_object->pager->pg_type == PG_SWAP || (src_object->flags & OBJ_INTERNAL)) { /* @@ -1127,91 +1150,6 @@ vm_object_remove(pager) } } -static void -vm_object_rcollapse(object, sobject) - register vm_object_t object, sobject; -{ - register vm_object_t backing_object; - register vm_offset_t backing_offset, new_offset; - register vm_page_t p, pp; - register vm_size_t size; - int s; - - if (!object) - return; - backing_object = object->shadow; - if (backing_object != sobject) { - printf("backing obj != sobject!!!\n"); - return; - } - if (!backing_object) - return; - if ((backing_object->flags & OBJ_INTERNAL) == 0) - return; - if (backing_object->shadow != NULL && - backing_object->shadow->copy == backing_object) - return; - if (backing_object->ref_count != 1) - return; - - object->ref_count += 2; - backing_object->ref_count += 2; - - backing_offset = object->shadow_offset; - size = object->size; - -again: - s = splbio(); - /* XXX what about object->paging_in_progress? */ - while (backing_object->paging_in_progress) { - tsleep(backing_object, PVM, "rcolpp", 0); - } - splx(s); - - p = backing_object->memq.tqh_first; - while (p) { - vm_page_t next; - - 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 = next; - continue; - } - pmap_page_protect(VM_PAGE_TO_PHYS(p), VM_PROT_NONE); - new_offset = (p->offset - backing_offset); - if (p->offset < backing_offset || - new_offset >= size) { - if (backing_object->pager) - swap_pager_freespace(backing_object->pager, - backing_object->paging_offset + p->offset, PAGE_SIZE); - vm_page_lock_queues(); - vm_page_free(p); - vm_page_unlock_queues(); - } else { - pp = vm_page_lookup(object, new_offset); - if (pp != NULL || - (object->pager && - vm_pager_has_page(object->pager, object->paging_offset + new_offset))) { - if (backing_object->pager) - swap_pager_freespace(backing_object->pager, - backing_object->paging_offset + p->offset, PAGE_SIZE); - vm_page_lock_queues(); - vm_page_free(p); - vm_page_unlock_queues(); - } else { - if (!backing_object->pager || - !vm_pager_has_page(backing_object->pager, backing_object->paging_offset + p->offset)) - vm_page_rename(p, object, new_offset); - } - } - p = next; - } - backing_object->ref_count -= 2; - object->ref_count -= 2; -} - /* * this version of collapse allows the operation to occur earlier and * when paging_in_progress is true for an object... This is not a complete @@ -1272,9 +1210,10 @@ vm_object_qcollapse(object) vm_page_free(p); vm_page_unlock_queues(); } else { - if (!backing_object->pager || - !vm_pager_has_page(backing_object->pager, backing_object->paging_offset + p->offset)) - vm_page_rename(p, object, new_offset); + if( backing_object->pager) + swap_pager_freespace(backing_object->pager, + backing_object->paging_offset + p->offset, PAGE_SIZE); + vm_page_rename(p, object, new_offset); } } p = next; @@ -1347,8 +1286,8 @@ vm_object_collapse(object) if ((backing_object->flags & OBJ_INTERNAL) == 0 || backing_object->paging_in_progress != 0) { - vm_object_unlock(backing_object); vm_object_qcollapse(object); + vm_object_unlock(backing_object); return; } /* @@ -1391,6 +1330,7 @@ vm_object_collapse(object) if (backing_object->ref_count == 1) { + backing_object->flags |= OBJ_DEAD; /* * We can collapse the backing object. * @@ -1784,6 +1724,128 @@ vm_object_page_lookup(object, offset) return m; } +int +_vm_object_in_map(map, object, entry) + vm_map_t map; + vm_object_t object; + vm_map_entry_t entry; +{ + vm_map_t tmpm; + vm_map_entry_t tmpe; + vm_object_t obj; + int entcount; + + if (map == 0) + return 0; + + if (entry == 0) { + tmpe = map->header.next; + entcount = map->nentries; + while (entcount-- && (tmpe != &map->header)) { + if( _vm_object_in_map(map, object, tmpe)) { + return 1; + } + tmpe = tmpe->next; + } + } else if (entry->is_sub_map || entry->is_a_map) { + tmpm = entry->object.share_map; + tmpe = tmpm->header.next; + entcount = tmpm->nentries; + while (entcount-- && tmpe != &tmpm->header) { + if( _vm_object_in_map(tmpm, object, tmpe)) { + return 1; + } + tmpe = tmpe->next; + } + } else if (obj = entry->object.vm_object) { + for(; obj; obj=obj->shadow) + if( obj == object) { + return 1; + } + } + return 0; +} + +int +vm_object_in_map( object) + vm_object_t object; +{ + struct proc *p; + for (p = (struct proc *) allproc; p != NULL; p = p->p_next) { + if( !p->p_vmspace /* || (p->p_flag & (P_SYSTEM|P_WEXIT)) */) + continue; +/* + if (p->p_stat != SRUN && p->p_stat != SSLEEP) { + continue; + } +*/ + if( _vm_object_in_map(&p->p_vmspace->vm_map, object, 0)) + return 1; + } + if( _vm_object_in_map( kernel_map, object, 0)) + return 1; + if( _vm_object_in_map( kmem_map, object, 0)) + return 1; + if( _vm_object_in_map( pager_map, object, 0)) + return 1; + if( _vm_object_in_map( buffer_map, object, 0)) + return 1; + if( _vm_object_in_map( io_map, object, 0)) + return 1; + if( _vm_object_in_map( phys_map, object, 0)) + return 1; + if( _vm_object_in_map( mb_map, object, 0)) + return 1; + if( _vm_object_in_map( u_map, object, 0)) + return 1; + return 0; +} + +void +vm_object_check() { + int i; + int maxhash = 0; + vm_object_t object; + vm_object_hash_entry_t entry; + + /* + * make sure that no internal objs are hashed + */ + for (i=0; i<VM_OBJECT_HASH_COUNT;i++) { + int lsize = 0; + for (entry = vm_object_hashtable[i].tqh_first; + entry != NULL; + entry = entry->hash_links.tqe_next) { + if( entry->object->flags & OBJ_INTERNAL) { + printf("vmochk: internal obj on hash: size: %d\n", entry->object->size); + } + ++lsize; + } + if( lsize > maxhash) + maxhash = lsize; + } + + printf("maximum object hash queue size: %d\n", maxhash); + + /* + * make sure that internal objs are in a map somewhere + * and none have zero ref counts. + */ + for (object = vm_object_list.tqh_first; + object != NULL; + object = object->object_list.tqe_next) { + if( object->flags & OBJ_INTERNAL) { + if( object->ref_count == 0) { + printf("vmochk: internal obj has zero ref count: %d\n", + object->size); + } + if( !vm_object_in_map(object)) { + printf("vmochk: internal obj is not in a map: ref: %d, size: %d, pager: 0x%x, shadow: 0x%x\n", object->ref_count, object->size, object->pager, object->shadow); + } + } + } +} + #define DEBUG #if defined(DEBUG) || defined(DDB) /* |