From a5ab72bc176e679e362c9c6125e3e3da954263e7 Mon Sep 17 00:00:00 2001 From: Richard Braun Date: Wed, 12 May 2032 03:15:41 +0200 Subject: VM: fix pageout throttling to external pagers Since the VM system has been tracking whether pages belong to internal or external objects, pageout throttling to external pagers has simply not been working. The reason is that, on pageout, requests for external pages are correctly tracked, but on page release (which is used to acknowledge the request), external pages are not marked external any more. This is because the external bit tracks whether a page belongs to an external object, and all pages, including external ones, are moved to an internal object during pageout. To solve this issue, a new "external_laundry" bit is added. It has the same purpose as the laundry bit, but for external pagers. * vm/vm_page.c (vm_page_seg_min_page_available): Function unused, remove. (vm_page_seg_evict): Use vm_page_external_laundry_count instead of vm_page_external_pagedout. Add an assertion about double paging. (vm_page_check_usable): Use vm_page_external_laundry_count instead of vm_page_external_pagedout. (vm_page_evict): Likewise. * vm/vm_page.h (struct vm_page): New `external_laundry' member. (vm_page_external_pagedout): Rename to ... (vm_page_external_laundry_count): ... this. * vm/vm_pageout.c: Include kern/printf.h. (DEBUG): New macro. (VM_PAGEOUT_TIMEOUT): Likewise. (vm_pageout_setup): Use vm_page_external_laundry_count instead of vm_page_external_pagedout. Set `external_laundry' where appropriate. (vm_pageout): Use VM_PAGEOUT_TIMEOUT with thread_set_timeout. Add debugging code, commented out by default. * vm/vm_resident.c (vm_page_external_pagedout): Rename to ... (vm_page_external_laundry_count): ... this. (vm_page_init_template): Set `external_laundry' member to FALSE. (vm_page_release): Rename external parameter to external_laundry. Slightly change pageout resuming. (vm_page_free): Rename external variable to external_laundry. --- vm/vm_pageout.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'vm/vm_pageout.c') diff --git a/vm/vm_pageout.c b/vm/vm_pageout.c index 85db021e..7dc9c12f 100644 --- a/vm/vm_pageout.c +++ b/vm/vm_pageout.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,13 @@ #include #include +#define DEBUG 0 + +/* + * Maximum delay, in milliseconds, between two pageout scans. + */ +#define VM_PAGEOUT_TIMEOUT 50 + /* * Event placeholder for pageout requests, synchronized with * the free page queue lock. @@ -251,17 +259,19 @@ vm_pageout_setup( vm_page_wire(m); } else { - vm_page_activate(m); + m->external_laundry = TRUE; /* - * If vm_page_external_pagedout is negative, + * If vm_page_external_laundry_count is negative, * the pageout daemon isn't expecting to be * notified. */ - if (vm_page_external_pagedout >= 0) { - vm_page_external_pagedout++; + if (vm_page_external_laundry_count >= 0) { + vm_page_external_laundry_count++; } + + vm_page_activate(m); } vm_page_unlock_queues(); @@ -460,9 +470,19 @@ void vm_pageout(void) FALSE); } else if (should_wait) { assert_wait(&vm_pageout_continue, FALSE); - thread_set_timeout(500); + thread_set_timeout(VM_PAGEOUT_TIMEOUT); simple_unlock(&vm_page_queue_free_lock); thread_block(NULL); + +#if DEBUG + if (current_thread()->wait_result != THREAD_AWAKENED) { + printf("vm_pageout: timeout," + " vm_page_laundry_count:%d" + " vm_page_external_laundry_count:%d\n", + vm_page_laundry_count, + vm_page_external_laundry_count); + } +#endif } else { simple_unlock(&vm_page_queue_free_lock); } -- cgit v1.2.3