summaryrefslogtreecommitdiff
path: root/vm/vm_resident.c
diff options
context:
space:
mode:
authorSergio Lopez <slp@sinrega.org>2011-12-29 22:30:12 +0100
committerSergio Lopez <slp@sinrega.org>2011-12-29 22:30:12 +0100
commit666299d037be6ffa83345d6d281fa955431f55fe (patch)
treef63ff542ac6bbe6d6d99fa17348a5ca958685227 /vm/vm_resident.c
parent6af53cb9d48013971ad5fa37de173c1bbf73292a (diff)
* include/mach/memory_object.h: Add MEMORY_OBJECT_COPY_VMPRIV to mark objects that can't be blocked even if dirty page limits has been exceeded.k0ro/advisory_pageout/master
* vm/memory_object.c (memory_object_data_supply): Mark pages provided by user as external. * (memory_object_lock_request): Lock page queues before cleaning holding pages. * (memory_object_set_attributes_common): Deal with MEMORY_OBJECT_COPY_VMPRIV. * vm/vm_fault.c (vm_fault_page): If the number of potentially dirty pages has reached a certain static number, either request a pageout or block the thread. * (vm_fault_page): Force an early request for a real page instead of a fictitious one. * vm/vm_object.h (struct vm_object): New flag vm_privileged that relates with MEMORY_OBJECT_COPY_PRIV. * vm/vm_object.c (vm_object_bootstrap): Initialize vm_privileged property as FALSE. * vm/vm_page.h: Add variables vm_page_too_dirty, vm_page_dirty_count and vm_page_external_target. * vm/vm_pageout.c: Adjust VM_PAGE_FREE_TARGET, VM_PAGE_FREE_MIN and VM_PAGE_EXTERNAL_LIMIT. Make vm_page_external_target signed. * (vm_pageout_setup): Write lock cleaned pages. Adjust dirty page counters. * (vm_pageout_scan): Try freeing clean external pages first. Disable broken old code. * vm/vm_resident.c: Add variables vm_page_too_dirty and vm_page_dirty_count. * (vm_page_convert.c): Propagate external argument to converted page. * (vm_page_grab): Don't use old external page limits. * (vm_page_grab_contiguous_pages): Likewise. * (vm_page_wait): Likewise. * (vm_page_release): Don't adjust external count. * (vm_page_free): Adjust external and external-dirty counters here. Wake up blocked threads.
Diffstat (limited to 'vm/vm_resident.c')
-rw-r--r--vm/vm_resident.c31
1 files changed, 21 insertions, 10 deletions
diff --git a/vm/vm_resident.c b/vm/vm_resident.c
index 96354a45..d3db6869 100644
--- a/vm/vm_resident.c
+++ b/vm/vm_resident.c
@@ -162,6 +162,8 @@ int vm_page_inactive_target = 0;
int vm_page_free_reserved = 0;
int vm_page_laundry_count = 0;
int vm_page_external_limit = 0;
+int vm_page_too_dirty = 0;
+int vm_page_dirty_count = 0;
/*
@@ -207,6 +209,7 @@ void vm_page_bootstrap(
m->laundry = FALSE;
m->free = FALSE;
m->external = FALSE;
+ m->overwriting = FALSE;
m->busy = TRUE;
m->wanted = FALSE;
@@ -838,6 +841,7 @@ boolean_t vm_page_convert(
m->phys_addr = real_m->phys_addr;
m->fictitious = FALSE;
+ m->external = external;
real_m->phys_addr = vm_page_fictitious_addr;
real_m->fictitious = TRUE;
@@ -866,10 +870,8 @@ vm_page_t vm_page_grab(
* for externally-managed pages.
*/
- if (((vm_page_free_count < vm_page_free_reserved)
- || (external
- && (vm_page_external_count > vm_page_external_limit)))
- && !current_thread()->vm_privilege) {
+ if ((vm_page_free_count < vm_page_free_reserved) &&
+ !current_thread()->vm_privilege) {
simple_unlock(&vm_page_queue_free_lock);
return VM_PAGE_NULL;
}
@@ -979,8 +981,7 @@ vm_page_grab_contiguous_pages(
* Do not dip into the reserved pool.
*/
- if ((vm_page_free_count < vm_page_free_reserved)
- || (vm_page_external_count >= vm_page_external_limit)) {
+ if (vm_page_free_count < vm_page_free_reserved) {
printf_once("no more room for vm_page_grab_contiguous_pages");
simple_unlock(&vm_page_queue_free_lock);
return KERN_RESOURCE_SHORTAGE;
@@ -1163,8 +1164,6 @@ void vm_page_release(
mem->pageq.next = (queue_entry_t) vm_page_queue_free;
vm_page_queue_free = mem;
vm_page_free_count++;
- if (external)
- vm_page_external_count--;
/*
* Check if we should wake up someone waiting for page.
@@ -1215,8 +1214,7 @@ void vm_page_wait(
*/
simple_lock(&vm_page_queue_free_lock);
- if ((vm_page_free_count < vm_page_free_target)
- || (vm_page_external_count > vm_page_external_limit)) {
+ if (vm_page_free_count < vm_page_free_target) {
if (vm_page_free_wanted++ == 0)
thread_wakeup((event_t)&vm_page_free_wanted);
assert_wait((event_t)&vm_page_free_count, FALSE);
@@ -1292,6 +1290,19 @@ void vm_page_free(
if (mem->absent)
vm_object_absent_release(mem->object);
+ if (mem->external) {
+ vm_page_external_count--;
+ mem->external = FALSE;
+ if (mem->overwriting) {
+ vm_page_dirty_count--;
+ if (vm_page_too_dirty) {
+ vm_page_too_dirty--;
+ if (vm_page_too_dirty == 0)
+ thread_wakeup((event_t)&vm_page_too_dirty);
+ }
+ }
+ }
+
/*
* XXX The calls to vm_page_init here are
* really overkill.