Index: sys/kern/subr_pidctrl.c =================================================================== --- sys/kern/subr_pidctrl.c +++ sys/kern/subr_pidctrl.c @@ -35,6 +35,13 @@ #include #include +int +pidctrl_error(struct pidctrl *pc, int input) +{ + + return (pc->pc_setpoint - input); +} + void pidctrl_init(struct pidctrl *pc, int interval, int setpoint, int bound, int Kpd, int Kid, int Kdd) @@ -87,7 +94,7 @@ int output, error; int Kpd, Kid, Kdd; - error = pc->pc_setpoint - input; + error = pidctrl_error(pc, input); pc->pc_ticks = ticks; pc->pc_olderror = pc->pc_error; @@ -118,7 +125,8 @@ int output, error; int Kpd, Kid, Kdd; - error = pc->pc_setpoint - input; + error = pidctrl_error(pc, input); + /* * When ticks expires we reset our variables and start a new * interval. If we're called multiple times during one interval Index: sys/sys/pidctrl.h =================================================================== --- sys/sys/pidctrl.h +++ sys/sys/pidctrl.h @@ -90,6 +90,7 @@ struct sysctl_oid_list; +int pidctrl_error(struct pidctrl *pc, int input); void pidctrl_init(struct pidctrl *pc, int interval, int setpoint, int bound, int Kpd, int Kid, int Kdd); void pidctrl_init_sysctl(struct pidctrl *pc, struct sysctl_oid_list *parent); Index: sys/vm/vm_pageout.c =================================================================== --- sys/vm/vm_pageout.c +++ sys/vm/vm_pageout.c @@ -152,7 +152,6 @@ static int vm_pageout_update_period; static int disable_swap_pageouts; static int lowmem_period = 10; -static time_t lowmem_uptime; static int swapdev_enabled; static int vm_panic_on_oom = 0; @@ -1856,12 +1855,17 @@ } } -static void -vm_pageout_lowmem(struct vm_domain *vmd) +static bool +vm_pageout_lowmem(void) { + static int lowmem_ticks = 0; + int last; + + last = atomic_load_int(&lowmem_ticks); + while ((u_int)(ticks - last) / hz >= lowmem_period) { + if (atomic_fcmpset_int(&lowmem_ticks, &last, ticks) == 0) + continue; - if (vmd == VM_DOMAIN(0) && - time_uptime - lowmem_uptime >= lowmem_period) { /* * Decrease registered cache sizes. */ @@ -1873,14 +1877,16 @@ * drained above. */ uma_reclaim(); - lowmem_uptime = time_uptime; + return (true); } + return (false); } static void vm_pageout_worker(void *arg) { struct vm_domain *vmd; + u_int ofree; int addl_shortage, domain, shortage; bool target_met; @@ -1939,11 +1945,16 @@ /* * Use the controller to calculate how many pages to free in - * this interval, and scan the inactive queue. + * this interval, and scan the inactive queue. If the lowmem + * handlers appear to have freed up some pages, subtract the + * difference from the inactive queue scan target. */ shortage = pidctrl_daemon(&vmd->vmd_pid, vmd->vmd_free_count); if (shortage > 0) { - vm_pageout_lowmem(vmd); + ofree = vmd->vmd_free_count; + if (vm_pageout_lowmem() && vmd->vmd_free_count > ofree) + shortage -= min(vmd->vmd_free_count - ofree, + (u_int)shortage); target_met = vm_pageout_scan_inactive(vmd, shortage, &addl_shortage); } else