* Dispatch a number of inactive threads according to load and collect the * results to present a coherent view of paging activity on this domain. */
| 1652 | * results to present a coherent view of paging activity on this domain. |
| 1653 | */ |
| 1654 | static int |
| 1655 | vm_pageout_inactive_dispatch(struct vm_domain *vmd, int shortage) |
| 1656 | { |
| 1657 | u_int freed, pps, slop, threads, us; |
| 1658 | |
| 1659 | vmd->vmd_inactive_shortage = shortage; |
| 1660 | slop = 0; |
| 1661 | |
| 1662 | /* |
| 1663 | * If we have more work than we can do in a quarter of our interval, we |
| 1664 | * fire off multiple threads to process it. |
| 1665 | */ |
| 1666 | threads = vmd->vmd_inactive_threads; |
| 1667 | if (threads > 1 && vmd->vmd_inactive_pps != 0 && |
| 1668 | shortage > vmd->vmd_inactive_pps / VM_INACT_SCAN_RATE / 4) { |
| 1669 | vmd->vmd_inactive_shortage /= threads; |
| 1670 | slop = shortage % threads; |
| 1671 | vm_domain_pageout_lock(vmd); |
| 1672 | blockcount_acquire(&vmd->vmd_inactive_starting, threads - 1); |
| 1673 | blockcount_acquire(&vmd->vmd_inactive_running, threads - 1); |
| 1674 | wakeup(&vmd->vmd_inactive_shortage); |
| 1675 | vm_domain_pageout_unlock(vmd); |
| 1676 | } |
| 1677 | |
| 1678 | /* Run the local thread scan. */ |
| 1679 | vm_pageout_scan_inactive(vmd, vmd->vmd_inactive_shortage + slop); |
| 1680 | |
| 1681 | /* |
| 1682 | * Block until helper threads report results and then accumulate |
| 1683 | * totals. |
| 1684 | */ |
| 1685 | blockcount_wait(&vmd->vmd_inactive_running, NULL, "vmpoid", PVM); |
| 1686 | freed = atomic_readandclear_int(&vmd->vmd_inactive_freed); |
| 1687 | VM_CNT_ADD(v_dfree, freed); |
| 1688 | |
| 1689 | /* |
| 1690 | * Calculate the per-thread paging rate with an exponential decay of |
| 1691 | * prior results. Careful to avoid integer rounding errors with large |
| 1692 | * us values. |
| 1693 | */ |
| 1694 | us = max(atomic_readandclear_int(&vmd->vmd_inactive_us), 1); |
| 1695 | if (us > 1000000) |
| 1696 | /* Keep rounding to tenths */ |
| 1697 | pps = (freed * 10) / ((us * 10) / 1000000); |
| 1698 | else |
| 1699 | pps = (1000000 / us) * freed; |
| 1700 | vmd->vmd_inactive_pps = (vmd->vmd_inactive_pps / 2) + (pps / 2); |
| 1701 | |
| 1702 | return (shortage - freed); |
| 1703 | } |
| 1704 | |
| 1705 | /* |
| 1706 | * Attempt to reclaim the requested number of pages from the inactive queue. |
no test coverage detected