Index: sys/vm/vm_glue.c =================================================================== --- sys/vm/vm_glue.c +++ sys/vm/vm_glue.c @@ -68,6 +68,7 @@ #include #include +#include #include #include #include @@ -300,13 +301,30 @@ static int kstack_cache_size = 128; static int kstacks; static struct mtx kstack_cache_mtx; -MTX_SYSINIT(kstack_cache, &kstack_cache_mtx, "kstkch", MTX_DEF); +static struct domainset *kstack_domainset; SYSCTL_INT(_vm, OID_AUTO, kstack_cache_size, CTLFLAG_RW, &kstack_cache_size, 0, ""); SYSCTL_INT(_vm, OID_AUTO, kstacks, CTLFLAG_RD, &kstacks, 0, ""); +static void +kstack_init(void *dummy __unused) +{ + struct domainset dset; + int i; + + mtx_init(&kstack_cache_mtx, "kstkch", NULL, MTX_DEF); + + DOMAINSET_ZERO(&dset.ds_mask); + for (i = 0; i < vm_ndomains; i++) + DOMAINSET_SET(i, &dset.ds_mask); + dset.ds_policy = DOMAINSET_POLICY_ROUNDROBIN; + dset.ds_prefer = -1; + kstack_domainset = domainset_create(&dset); +} +SYSINIT(kstack_init, SI_SUB_VM_CONF, SI_ORDER_ANY, kstack_init, NULL); + /* * Create the kernel stack (including pcb for i386) for a new thread. * This routine directly affects the fork perf for a process and @@ -369,6 +387,14 @@ return (0); } + /* + * Ensure that kstack objects can draw pages from any memory + * domain. Otherwise a local memory shortage can block a process + * swap-in. + */ + ksobj->domain.dr_policy = kstack_domainset; + ksobj->domain.dr_iterator = 0; + atomic_add_int(&kstacks, 1); if (KSTACK_GUARD_PAGES != 0) { pmap_qremove(ks, KSTACK_GUARD_PAGES); Index: sys/vm/vm_object.c =================================================================== --- sys/vm/vm_object.c +++ sys/vm/vm_object.c @@ -274,6 +274,7 @@ panic("_vm_object_allocate: type %d is undefined", type); } object->size = size; + object->domain.dr_policy = NULL; object->generation = 1; object->ref_count = 1; object->memattr = VM_MEMATTR_DEFAULT; Index: sys/vm/vm_swapout.c =================================================================== --- sys/vm/vm_swapout.c +++ sys/vm/vm_swapout.c @@ -742,7 +742,7 @@ /* * Limit swapper to swap in one non-WKILLED process in MAXSLP/2 * interval, assuming that there is: - * - no memory shortage; + * - no global memory shortage; * - no parallel swap-ins; * - no other swap-ins in the current SWAPIN_INTERVAL. */ @@ -750,7 +750,7 @@ swapper_wkilled_only(void) { - return (vm_page_count_min() || swap_inprogress > 0 || + return (vm_page_count_min_set(&all_domains) || swap_inprogress > 0 || (u_int)(ticks - last_swapin) < SWAPIN_INTERVAL); }