* vm_fault_prefault provides a quick way of clustering * pagefaults into a processes address space. It is a "cousin" * of vm_map_pmap_enter, except it runs at page fault time instead * of mmap time. */
| 1711 | * of mmap time. |
| 1712 | */ |
| 1713 | static void |
| 1714 | vm_fault_prefault(const struct faultstate *fs, vm_offset_t addra, |
| 1715 | int backward, int forward, bool obj_locked) |
| 1716 | { |
| 1717 | pmap_t pmap; |
| 1718 | vm_map_entry_t entry; |
| 1719 | vm_object_t backing_object, lobject; |
| 1720 | vm_offset_t addr, starta; |
| 1721 | vm_pindex_t pindex; |
| 1722 | vm_page_t m; |
| 1723 | int i; |
| 1724 | |
| 1725 | pmap = fs->map->pmap; |
| 1726 | if (pmap != vmspace_pmap(curthread->td_proc->p_vmspace)) |
| 1727 | return; |
| 1728 | |
| 1729 | entry = fs->entry; |
| 1730 | |
| 1731 | if (addra < backward * PAGE_SIZE) { |
| 1732 | starta = entry->start; |
| 1733 | } else { |
| 1734 | starta = addra - backward * PAGE_SIZE; |
| 1735 | if (starta < entry->start) |
| 1736 | starta = entry->start; |
| 1737 | } |
| 1738 | |
| 1739 | /* |
| 1740 | * Generate the sequence of virtual addresses that are candidates for |
| 1741 | * prefaulting in an outward spiral from the faulting virtual address, |
| 1742 | * "addra". Specifically, the sequence is "addra - PAGE_SIZE", "addra |
| 1743 | * + PAGE_SIZE", "addra - 2 * PAGE_SIZE", "addra + 2 * PAGE_SIZE", ... |
| 1744 | * If the candidate address doesn't have a backing physical page, then |
| 1745 | * the loop immediately terminates. |
| 1746 | */ |
| 1747 | for (i = 0; i < 2 * imax(backward, forward); i++) { |
| 1748 | addr = addra + ((i >> 1) + 1) * ((i & 1) == 0 ? -PAGE_SIZE : |
| 1749 | PAGE_SIZE); |
| 1750 | if (addr > addra + forward * PAGE_SIZE) |
| 1751 | addr = 0; |
| 1752 | |
| 1753 | if (addr < starta || addr >= entry->end) |
| 1754 | continue; |
| 1755 | |
| 1756 | if (!pmap_is_prefaultable(pmap, addr)) |
| 1757 | continue; |
| 1758 | |
| 1759 | pindex = ((addr - entry->start) + entry->offset) >> PAGE_SHIFT; |
| 1760 | lobject = entry->object.vm_object; |
| 1761 | if (!obj_locked) |
| 1762 | VM_OBJECT_RLOCK(lobject); |
| 1763 | while ((m = vm_page_lookup(lobject, pindex)) == NULL && |
| 1764 | lobject->type == OBJT_DEFAULT && |
| 1765 | (backing_object = lobject->backing_object) != NULL) { |
| 1766 | KASSERT((lobject->backing_object_offset & PAGE_MASK) == |
| 1767 | 0, ("vm_fault_prefault: unaligned object offset")); |
| 1768 | pindex += lobject->backing_object_offset >> PAGE_SHIFT; |
| 1769 | VM_OBJECT_RLOCK(backing_object); |
| 1770 | if (!obj_locked || lobject != entry->object.vm_object) |
no test coverage detected