Make choice of external or internal pages for vm_page_seg_pull_inactive_page
and vm_page_seg_pull_active_page explicit rather than preferential. This will
allow future modifications to be more specific about exactly which type of
pages should be chosen for eviction.
There is only 1 change in behaviour with this modification. Previously pageout
would search external pages first, then external pages again before searching
internal pages. Now external pages are searched once only before internal
pages. This should make no practical difference.
---
vm/vm_page.c | 50 ++++++++++++++++++++++++++++++--------------------
1 file changed, 30 insertions(+), 20 deletions(-)
diff --git a/vm/vm_page.c b/vm/vm_page.c
index 0b3dfcbf..508e716b 100644
--- a/vm/vm_page.c
+++ b/vm/vm_page.c
@@ -829,7 +829,7 @@ vm_page_next_page_list(struct list* cur_page_list,
* If successful, the object containing the page is locked.
*/
static struct vm_page *
-vm_page_seg_pull_active_page(struct vm_page_seg *seg, boolean_t external_only)
+vm_page_seg_pull_active_page(struct vm_page_seg *seg, boolean_t external)
{
struct vm_page *page, *first;
struct list* page_list;
@@ -837,7 +837,9 @@ vm_page_seg_pull_active_page(struct vm_page_seg *seg,
boolean_t external_only)
first = NULL;
- page_list = &seg->active_pages.external_pages;
+ page_list = (external
+ ? &seg->active_pages.external_pages
+ : &seg->active_pages.internal_pages);
for (;;) {
@@ -846,7 +848,7 @@ vm_page_seg_pull_active_page(struct vm_page_seg *seg,
boolean_t external_only)
: list_first_entry(page_list, struct vm_page, node));
if (page == NULL || page == first) {
- page_list = vm_page_next_page_list(page_list, &seg->active_pages,
external_only);
+ page_list = NULL;
if (page_list == NULL)
break;
@@ -887,7 +889,7 @@ vm_page_seg_pull_active_page(struct vm_page_seg *seg,
boolean_t external_only)
* XXX See vm_page_seg_pull_active_page (duplicated code).
*/
static struct vm_page *
-vm_page_seg_pull_inactive_page(struct vm_page_seg *seg, boolean_t
external_only)
+vm_page_seg_pull_inactive_page(struct vm_page_seg *seg, boolean_t external)
{
struct vm_page *page, *first;
struct list* page_list;
@@ -895,7 +897,9 @@ vm_page_seg_pull_inactive_page(struct vm_page_seg *seg,
boolean_t external_only)
first = NULL;
- page_list = &seg->inactive_pages.external_pages;
+ page_list = (external
+ ? &seg->inactive_pages.external_pages
+ : &seg->inactive_pages.internal_pages);
for (;;) {
@@ -904,7 +908,7 @@ vm_page_seg_pull_inactive_page(struct vm_page_seg *seg,
boolean_t external_only)
: list_first_entry(page_list, struct vm_page, node));
if (page == NULL || page == first) {
- page_list = vm_page_next_page_list(page_list, &seg->inactive_pages,
external_only);
+ page_list = NULL;
if (page_list == NULL)
break;
@@ -944,19 +948,19 @@ vm_page_seg_pull_inactive_page(struct vm_page_seg *seg,
boolean_t external_only)
*/
static struct vm_page *
vm_page_seg_pull_cache_page(struct vm_page_seg *seg,
- boolean_t external_only,
+ boolean_t external,
boolean_t *was_active)
{
struct vm_page *page;
- page = vm_page_seg_pull_inactive_page(seg, external_only);
+ page = vm_page_seg_pull_inactive_page(seg, external);
if (page != NULL) {
*was_active = FALSE;
return page;
}
- page = vm_page_seg_pull_active_page(seg, external_only);
+ page = vm_page_seg_pull_active_page(seg, external);
if (page != NULL) {
*was_active = TRUE;
@@ -1027,7 +1031,10 @@ vm_page_seg_balance_page(struct vm_page_seg *seg,
goto error;
}
- src = vm_page_seg_pull_cache_page(seg, FALSE, &was_active);
+ src = vm_page_seg_pull_cache_page(seg, TRUE, &was_active);
+
+ if (src == NULL)
+ src = vm_page_seg_pull_cache_page(seg, FALSE, &was_active);
if (src == NULL) {
goto error;
@@ -1129,7 +1136,7 @@ vm_page_seg_balance(struct vm_page_seg *seg)
}
static boolean_t
-vm_page_seg_evict(struct vm_page_seg *seg, boolean_t external_only,
+vm_page_seg_evict(struct vm_page_seg *seg, boolean_t external,
boolean_t alloc_paused)
{
struct vm_page *page;
@@ -1148,7 +1155,7 @@ restart:
if (page != NULL) {
vm_object_lock(page->object);
} else {
- page = vm_page_seg_pull_cache_page(seg, external_only, &was_active);
+ page = vm_page_seg_pull_cache_page(seg, external, &was_active);
if (page == NULL) {
goto out;
@@ -1292,7 +1299,10 @@ vm_page_seg_refill_inactive(struct vm_page_seg *seg)
vm_page_seg_compute_high_active_page(seg);
while (seg->nr_active_pages > seg->high_active_pages) {
- page = vm_page_seg_pull_active_page(seg, FALSE);
+ page = vm_page_seg_pull_active_page(seg, TRUE);
+
+ if (page == NULL)
+ page = vm_page_seg_pull_active_page(seg, FALSE);
if (page == NULL) {
break;
@@ -2021,7 +2031,7 @@ vm_page_balance(void)
}
static boolean_t
-vm_page_evict_once(boolean_t external_only, boolean_t alloc_paused)
+vm_page_evict_once(boolean_t external, boolean_t alloc_paused)
{
boolean_t evicted;
unsigned int i;
@@ -2033,7 +2043,7 @@ vm_page_evict_once(boolean_t external_only, boolean_t
alloc_paused)
for (i = vm_page_segs_size - 1; i < vm_page_segs_size; i--) {
evicted = vm_page_seg_evict(vm_page_seg_get(i),
- external_only, alloc_paused);
+ external, alloc_paused);
if (evicted) {
return TRUE;
@@ -2049,11 +2059,11 @@ vm_page_evict_once(boolean_t external_only, boolean_t
alloc_paused)
boolean_t
vm_page_evict(boolean_t *should_wait)
{
- boolean_t pause, evicted, external_only, alloc_paused;
+ boolean_t pause, evicted, external, alloc_paused;
unsigned int i;
*should_wait = TRUE;
- external_only = TRUE;
+ external = TRUE;
simple_lock(&vm_page_queue_free_lock);
vm_page_external_laundry_count = 0;
@@ -2071,7 +2081,7 @@ again:
}
for (i = 0; i < VM_PAGE_MAX_EVICTIONS; i++) {
- evicted = vm_page_evict_once(external_only, alloc_paused);
+ evicted = vm_page_evict_once(external, alloc_paused);
if (!evicted) {
break;
@@ -2098,9 +2108,9 @@ again:
* Eviction failed, consider pages from internal objects on the
* next attempt.
*/
- if (external_only && IP_VALID(memory_manager_default)) {
+ if (external && IP_VALID(memory_manager_default)) {
simple_unlock(&vm_page_queue_free_lock);
- external_only = FALSE;
+ external = FALSE;
goto again;
}
--
2.47.3