diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 3d96d9e..d8fbb71 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -1153,8 +1185,8 @@ unlock_and_continue: } /* - * The count for pagedaemon pages is done after checking the - * page for eligibility... + * The count for pageout daemon pages is done after checking + * the page for eligibility... */ cnt.v_pdpages++; @@ -1463,39 +1499,83 @@ vm_pageout() int error, pass; /* - * Initialize some paging parameters. + * Initialize some paging parameters. Generally speaking, the addends + * in each of the following assignments are ordered from left to right + * by their expected value, with the largest valued addend being on + * the left. */ cnt.v_interrupt_free_min = 2; + cnt.v_pageout_free_min = (2 * MAXBSIZE) / PAGE_SIZE + + cnt.v_interrupt_free_min; if (cnt.v_page_count < 2000) vm_pageout_page_count = 8; /* * v_free_reserved needs to include enough for the largest - * swap pager structures plus enough for any pv_entry structs - * when paging. + * swap pager structures. */ + cnt.v_free_reserved = (cnt.v_page_count / 768) + vm_pageout_page_count + + cnt.v_pageout_free_min; if (cnt.v_page_count > 1024) - cnt.v_free_min = 4 + (cnt.v_page_count - 1024) / 200; + cnt.v_free_min = (cnt.v_page_count - 1024) / 200 + 4; else cnt.v_free_min = 4; - cnt.v_pageout_free_min = (2*MAXBSIZE)/PAGE_SIZE + - cnt.v_interrupt_free_min; - cnt.v_free_reserved = vm_pageout_page_count + - cnt.v_pageout_free_min + (cnt.v_page_count / 768); - cnt.v_free_severe = cnt.v_free_min / 2; + cnt.v_free_severe = cnt.v_free_min / 2 + cnt.v_free_reserved; cnt.v_free_min += cnt.v_free_reserved; - cnt.v_free_severe += cnt.v_free_reserved; /* * v_free_target and v_cache_min control pageout hysteresis. Note * that these are more a measure of the VM cache queue hysteresis * then the VM free queue. Specifically, v_free_target is the * high water mark (free+cache pages). + * Note though that v_free_target + v_cache_min sets a "soft" target + * for pageout daemon page scan pass, the pageout daemon would make + * a best effort to reach that target, it would not go over the target, + * but inability to reach the target doesn't imply another pass. * * v_free_reserved + v_cache_min (mostly means v_cache_min) is the * low water mark, while v_free_min is the stop. v_cache_min must * be big enough to handle memory needs while the pageout daemon * is signalled and run to free more pages. + * Page allocation will fail for non-system requests when available + * memory goes below v_free_reserved. + * A page scan will be triggered by vm_page_alloc if available memory + * goes below v_free_reserved + v_cache_min (paging-needed threshold). + * Processes waiting on free pages are waken up when available memory + * goes above v_free_min (minimum low-free-pages threshold). + */ + /*- + * Important levels of available pages (v_free_count + v_cache_count), + * from higher to lower: + * | + * v + * o v_cache_min + v_free_target - a level that a page scan pass tries + * | to reach; at this level vm_paging_target() == 0. + * v + * o v_cache_min + v_free_reserved - a level below which vm_page_alloc + * | still succeeds, but does set vm_pages_needed flag and triggers + * | a page scan; vm_paging_needed() == 1 below this level. + * v + * o v_free_min - at this level threads waiting for pages are waked up + * | after page shortage (and vm_pages_needed flag is reset) in + * | vm_page_free_wakeup; vm_page_count_min() == 1 below this level. + * | vm_page_free_wakeup is called by vm_page_free_toq and + * | vm_page_cache, that is upon increasing available pages count. + * v + * o v_free_severe - below this level some users of vm_page_alloc + * | decide to not call it but rather wait until more pages are + * | available. Important cases of this check are: vm_fault and + * | vm_forkproc. vm_page_count_severe() == 1 below this level. + * v + * o v_free_reserved - at this level vm_page_alloc would return NULL + * | for normal requests and a page scan would be triggered; threads + * | needing memory would call VM_WAIT before retrying. + * v + * o v_interrupt_free_min - at this level vm_page_alloc would fail even + * | for VM_ALLOC_SYSTEM requests. + * v + * o Zero - with zero available pages vm_page_alloc would fail for all + * requests including VM_ALLOC_INTERRUPT. */ if (cnt.v_free_count > 6144) cnt.v_free_target = 4 * cnt.v_free_min + cnt.v_free_reserved; @@ -1506,13 +1586,13 @@ vm_pageout() cnt.v_cache_min = cnt.v_free_target; cnt.v_cache_max = 2 * cnt.v_cache_min; cnt.v_inactive_target = (3 * cnt.v_free_target) / 2; + if (cnt.v_inactive_target > cnt.v_free_count / 3) + cnt.v_inactive_target = cnt.v_free_count / 3; } else { cnt.v_cache_min = 0; cnt.v_cache_max = 0; cnt.v_inactive_target = cnt.v_free_count / 4; } - if (cnt.v_inactive_target > cnt.v_free_count / 3) - cnt.v_inactive_target = cnt.v_free_count / 3; /* XXX does not really belong here */ if (vm_page_max_wired == 0) @@ -1536,10 +1616,15 @@ vm_pageout() */ while (TRUE) { /* - * If we have enough free memory, wakeup waiters. Do - * not clear vm_pages_needed until we reach our target, - * otherwise we may be woken up over and over again and - * waste a lot of cpu. + * If we are above minimum low-free-pages threshold, wakeup + * waiters. Do not clear vm_pages_needed until we go above + * paging-needed threshold. + * Note that vm_pages_needed may already be cleared + * and waiters woken up by vm_page_free_wakeup routine, + * which is called e.g. when pages are moved to free or cache + * state. Also note that vm_page_free_wakeup would do that + * when we are above low-free-pages threshold, which is lower + * than the paging-needed threshold. */ mtx_lock(&vm_page_queue_free_mtx); if (vm_pages_needed && !vm_page_count_min()) { diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index d778c99..3dffb17 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -573,7 +573,7 @@ vm_page_io_finish(vm_page_t m) } /* - * Keep page from being freed by the page daemon + * Keep page from being freed by the pageout daemon * much of the same effect as wiring, except much lower * overhead and should be used only for *very* temporary * holding ("wiring"). @@ -1623,7 +1623,7 @@ vm_page_free_wakeup(void) mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); /* - * if pageout daemon needs pages, then tell it that there are + * If the pageout daemon needs pages, then tell it that there are * some free. */ if (vm_pageout_pages_needed && @@ -1632,9 +1632,10 @@ vm_page_free_wakeup(void) vm_pageout_pages_needed = 0; } /* - * wakeup processes that are waiting on memory if we hit a - * high water mark. And wakeup scheduler process if we have - * lots of memory. this process will swapin processes. + * Wakeup processes that are waiting on memory if the number of free + * pages exceeds the lowest threshold. + * This is a lower threshold than the pageout daemon uses for doing + * the same kind of wakeup after a page scan pass. */ if (vm_pages_needed && !vm_page_count_min()) { vm_pages_needed = 0; @@ -2083,7 +2084,7 @@ vm_page_dontneed(vm_page_t m) } /* - * Clear any references to the page. Otherwise, the page daemon will + * Clear any references to the page. Otherwise, the pageout daemon will * immediately reactivate the page. * * Perform the pmap_clear_reference() first. Otherwise, a concurrent @@ -2142,7 +2143,7 @@ retrylookup: ((allocflags & VM_ALLOC_IGN_SBUSY) == 0 && m->busy != 0)) { /* * Reference the page before unlocking and - * sleeping so that the page daemon is less + * sleeping so that the pageout daemon is less * likely to reclaim it. */ vm_page_lock_queues(); diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index f9a0179..302d7a5 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -333,7 +333,7 @@ RetryFault:; if ((fs.m->oflags & VPO_BUSY) || fs.m->busy) { /* * Reference the page before unlocking and - * sleeping so that the page daemon is less + * sleeping so that the pageout daemon is less * likely to reclaim it. */ vm_page_lock_queues(); diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 83039b2..a1a80a6 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -1080,7 +1080,7 @@ shadowlookup: if (advise == MADV_WILLNEED) { /* * Reference the page before unlocking and - * sleeping so that the page daemon is less + * sleeping so that the pageout daemon is less * likely to reclaim it. */ vm_page_lock_queues();