Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_domainset.c
| Show First 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | vm_domainset_iter_interleave(struct vm_domainset_iter *di, int *domain) | ||||
| *di->di_iter = d; | *di->di_iter = d; | ||||
| *domain = di->di_domain->ds_order[d]; | *domain = di->di_domain->ds_order[d]; | ||||
| } | } | ||||
| static void | static void | ||||
| vm_domainset_iter_next(struct vm_domainset_iter *di, int *domain) | vm_domainset_iter_next(struct vm_domainset_iter *di, int *domain) | ||||
| { | { | ||||
| KASSERT(di->di_n > 0, ("%s: Invalid n %d", __func__, di->di_n)); | KASSERT(!DOMAINSET_EMPTY(&di->di_remain_mask), | ||||
| ("%s: Already iterated on all domains", __func__)); | |||||
| switch (di->di_policy) { | switch (di->di_policy) { | ||||
| case DOMAINSET_POLICY_FIRSTTOUCH: | case DOMAINSET_POLICY_FIRSTTOUCH: | ||||
| /* | /* | ||||
| * To prevent impossible allocations we convert an invalid | * To prevent impossible allocations we convert an invalid | ||||
| * first-touch to round-robin. | * first-touch to round-robin. | ||||
| */ | */ | ||||
| /* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
| case DOMAINSET_POLICY_INTERLEAVE: | case DOMAINSET_POLICY_INTERLEAVE: | ||||
| Show All 13 Lines | |||||
| static void | static void | ||||
| vm_domainset_iter_first(struct vm_domainset_iter *di, int *domain) | vm_domainset_iter_first(struct vm_domainset_iter *di, int *domain) | ||||
| { | { | ||||
| switch (di->di_policy) { | switch (di->di_policy) { | ||||
| case DOMAINSET_POLICY_FIRSTTOUCH: | case DOMAINSET_POLICY_FIRSTTOUCH: | ||||
| *domain = PCPU_GET(domain); | *domain = PCPU_GET(domain); | ||||
| if (DOMAINSET_ISSET(*domain, &di->di_valid_mask)) { | if (DOMAINSET_ISSET(*domain, &di->di_valid_mask)) | ||||
| /* | |||||
| * Add an extra iteration because we will visit the | |||||
| * current domain a second time in the rr iterator. | |||||
| */ | |||||
| di->di_n = di->di_domain->ds_cnt + 1; | |||||
| break; | break; | ||||
| } | |||||
| /* | /* | ||||
| * To prevent impossible allocations we convert an invalid | * To prevent impossible allocations we convert an invalid | ||||
| * first-touch to round-robin. | * first-touch to round-robin. | ||||
| */ | */ | ||||
| /* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
| case DOMAINSET_POLICY_ROUNDROBIN: | case DOMAINSET_POLICY_ROUNDROBIN: | ||||
| di->di_n = di->di_domain->ds_cnt; | |||||
| vm_domainset_iter_rr(di, domain); | vm_domainset_iter_rr(di, domain); | ||||
| break; | break; | ||||
| case DOMAINSET_POLICY_PREFER: | case DOMAINSET_POLICY_PREFER: | ||||
| *domain = di->di_domain->ds_prefer; | *domain = di->di_domain->ds_prefer; | ||||
| di->di_n = di->di_domain->ds_cnt; | |||||
| break; | break; | ||||
| case DOMAINSET_POLICY_INTERLEAVE: | case DOMAINSET_POLICY_INTERLEAVE: | ||||
| vm_domainset_iter_interleave(di, domain); | vm_domainset_iter_interleave(di, domain); | ||||
| di->di_n = di->di_domain->ds_cnt; | |||||
| break; | break; | ||||
| default: | default: | ||||
| panic("%s: Unknown policy %d", __func__, di->di_policy); | panic("%s: Unknown policy %d", __func__, di->di_policy); | ||||
| } | } | ||||
| KASSERT(di->di_n > 0, ("%s: Invalid n %d", __func__, di->di_n)); | |||||
| KASSERT(*domain < vm_ndomains, | KASSERT(*domain < vm_ndomains, | ||||
| ("%s: Invalid domain %d", __func__, *domain)); | ("%s: Invalid domain %d", __func__, *domain)); | ||||
| /* Initialize the mask of domains to visit. */ | |||||
| if (di->di_minskip) { | |||||
| /* Phase 1: Skip domains under 'v_free_min'. */ | |||||
| DOMAINSET_COPY(&di->di_valid_mask, &di->di_remain_mask); | |||||
| DOMAINSET_ZERO(&di->di_min_mask); | |||||
| } else | |||||
| /* Phase 2: Browse domains that were under 'v_free_min'. */ | |||||
| DOMAINSET_COPY(&di->di_min_mask, &di->di_remain_mask); | |||||
| /* Mark first domain as seen. */ | |||||
| DOMAINSET_CLR(*domain, &di->di_remain_mask); | |||||
| } | } | ||||
| void | void | ||||
| vm_domainset_iter_page_init(struct vm_domainset_iter *di, struct vm_object *obj, | vm_domainset_iter_page_init(struct vm_domainset_iter *di, struct vm_object *obj, | ||||
| vm_pindex_t pindex, int *domain, int *req, struct pctrie_iter *pages) | vm_pindex_t pindex, int *domain, int *req, struct pctrie_iter *pages) | ||||
| { | { | ||||
| struct domainset_ref *dr; | struct domainset_ref *dr; | ||||
| Show All 17 Lines | |||||
| int | int | ||||
| vm_domainset_iter_page(struct vm_domainset_iter *di, struct vm_object *obj, | vm_domainset_iter_page(struct vm_domainset_iter *di, struct vm_object *obj, | ||||
| int *domain, struct pctrie_iter *pages) | int *domain, struct pctrie_iter *pages) | ||||
| { | { | ||||
| if (__predict_false(DOMAINSET_EMPTY(&di->di_valid_mask))) | if (__predict_false(DOMAINSET_EMPTY(&di->di_valid_mask))) | ||||
| return (ENOMEM); | return (ENOMEM); | ||||
| /* If there are more domains to visit we run the iterator. */ | /* If there are more domains to visit in this phase, run the iterator. */ | ||||
| while (--di->di_n != 0) { | while (!DOMAINSET_EMPTY(&di->di_remain_mask)) { | ||||
| vm_domainset_iter_next(di, domain); | vm_domainset_iter_next(di, domain); | ||||
| if (DOMAINSET_ISSET(*domain, &di->di_valid_mask) && | if (DOMAINSET_ISSET(*domain, &di->di_remain_mask)) { | ||||
| (!di->di_minskip || !vm_page_count_min_domain(*domain))) | DOMAINSET_CLR(*domain, &di->di_remain_mask); | ||||
| if (!di->di_minskip || !vm_page_count_min_domain(*domain)) | |||||
| return (0); | return (0); | ||||
| DOMAINSET_SET(*domain, &di->di_min_mask); | |||||
| } | } | ||||
| } | |||||
| /* If we skipped domains below min restart the search. */ | /* If we skipped domains below min restart the search. */ | ||||
| if (di->di_minskip) { | if (di->di_minskip) { | ||||
| di->di_minskip = false; | di->di_minskip = false; | ||||
| vm_domainset_iter_first(di, domain); | vm_domainset_iter_first(di, domain); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| int | int | ||||
| vm_domainset_iter_policy(struct vm_domainset_iter *di, int *domain) | vm_domainset_iter_policy(struct vm_domainset_iter *di, int *domain) | ||||
| { | { | ||||
| if (DOMAINSET_EMPTY(&di->di_valid_mask)) | if (DOMAINSET_EMPTY(&di->di_valid_mask)) | ||||
| return (ENOMEM); | return (ENOMEM); | ||||
| /* If there are more domains to visit we run the iterator. */ | /* If there are more domains to visit in this phase, run the iterator. */ | ||||
| while (--di->di_n != 0) { | while (!DOMAINSET_EMPTY(&di->di_remain_mask)) { | ||||
| vm_domainset_iter_next(di, domain); | vm_domainset_iter_next(di, domain); | ||||
| if (DOMAINSET_ISSET(*domain, &di->di_valid_mask) && | if (DOMAINSET_ISSET(*domain, &di->di_remain_mask)) { | ||||
| (!di->di_minskip || !vm_page_count_min_domain(*domain))) | DOMAINSET_CLR(*domain, &di->di_remain_mask); | ||||
| if (!di->di_minskip || !vm_page_count_min_domain(*domain)) | |||||
| return (0); | return (0); | ||||
| DOMAINSET_SET(*domain, &di->di_min_mask); | |||||
| } | |||||
| } | } | ||||
| /* If we skipped domains below min restart the search. */ | /* If we skipped domains below min restart the search. */ | ||||
| if (di->di_minskip) { | if (di->di_minskip) { | ||||
| di->di_minskip = false; | di->di_minskip = false; | ||||
| vm_domainset_iter_first(di, domain); | vm_domainset_iter_first(di, domain); | ||||
| return (0); | return (0); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 71 Lines • Show Last 20 Lines | |||||