diff options
author | alc <alc@FreeBSD.org> | 2002-06-02 23:54:09 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2002-06-02 23:54:09 +0000 |
commit | d75c291207e4793318a79b273deab25f974df642 (patch) | |
tree | 5d55699df959bb45d95b4e410e218a26ab4f0e75 /sys/vm/vm_object.c | |
parent | 70bffa5c2754c09fb8ac4e66c5639fcd58a370b8 (diff) | |
download | FreeBSD-src-d75c291207e4793318a79b273deab25f974df642.zip FreeBSD-src-d75c291207e4793318a79b273deab25f974df642.tar.gz |
o Migrate vm_map_split() from vm_map.c to vm_object.c, renaming it
to vm_object_split(). Its interface should still be changed
to resemble vm_object_shadow().
Diffstat (limited to 'sys/vm/vm_object.c')
-rw-r--r-- | sys/vm/vm_object.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 2760eba..d046941 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1180,6 +1180,97 @@ vm_object_shadow( mtx_unlock(&Giant); } +/* + * vm_object_split: + * + * Split the pages in a map entry into a new object. This affords + * easier removal of unused pages, and keeps object inheritance from + * being a negative impact on memory usage. + */ +void +vm_object_split(vm_map_entry_t entry) +{ + vm_page_t m; + vm_object_t orig_object, new_object, source; + vm_offset_t s, e; + vm_pindex_t offidxstart, offidxend, idx; + vm_size_t size; + vm_ooffset_t offset; + + GIANT_REQUIRED; + + orig_object = entry->object.vm_object; + if (orig_object->type != OBJT_DEFAULT && orig_object->type != OBJT_SWAP) + return; + if (orig_object->ref_count <= 1) + return; + + offset = entry->offset; + s = entry->start; + e = entry->end; + + offidxstart = OFF_TO_IDX(offset); + offidxend = offidxstart + OFF_TO_IDX(e - s); + size = offidxend - offidxstart; + + new_object = vm_pager_allocate(orig_object->type, + NULL, IDX_TO_OFF(size), VM_PROT_ALL, 0LL); + if (new_object == NULL) + return; + + source = orig_object->backing_object; + if (source != NULL) { + vm_object_reference(source); /* Referenced by new_object */ + TAILQ_INSERT_TAIL(&source->shadow_head, + new_object, shadow_list); + vm_object_clear_flag(source, OBJ_ONEMAPPING); + new_object->backing_object_offset = + orig_object->backing_object_offset + IDX_TO_OFF(offidxstart); + new_object->backing_object = source; + source->shadow_count++; + source->generation++; + } + for (idx = 0; idx < size; idx++) { + retry: + m = vm_page_lookup(orig_object, offidxstart + idx); + if (m == NULL) + continue; + + /* + * We must wait for pending I/O to complete before we can + * rename the page. + * + * We do not have to VM_PROT_NONE the page as mappings should + * not be changed by this operation. + */ + if (vm_page_sleep_busy(m, TRUE, "spltwt")) + goto retry; + + vm_page_busy(m); + vm_page_rename(m, new_object, idx); + /* page automatically made dirty by rename and cache handled */ + vm_page_busy(m); + } + if (orig_object->type == OBJT_SWAP) { + vm_object_pip_add(orig_object, 1); + /* + * copy orig_object pages into new_object + * and destroy unneeded pages in + * shadow object. + */ + swap_pager_copy(orig_object, new_object, offidxstart, 0); + vm_object_pip_wakeup(orig_object); + } + for (idx = 0; idx < size; idx++) { + m = vm_page_lookup(new_object, idx); + if (m != NULL) + vm_page_wakeup(m); + } + entry->object.vm_object = new_object; + entry->offset = 0LL; + vm_object_deallocate(orig_object); +} + #define OBSC_TEST_ALL_SHADOWED 0x0001 #define OBSC_COLLAPSE_NOWAIT 0x0002 #define OBSC_COLLAPSE_WAIT 0x0004 |