* vm_page_scan_contig: * * Scan vm_page_array[] between the specified entries "m_start" and * "m_end" for a run of contiguous physical pages that satisfy the * specified conditions, and return the lowest page in the run. The * specified "alignment" determines the alignment of the lowest physical * page in the run. If the specified "boundary" is non-zero, then the * run of physical pages c
| 2566 | * "alignment" and "boundary" must be a power of two. |
| 2567 | */ |
| 2568 | vm_page_t |
| 2569 | vm_page_scan_contig(u_long npages, vm_page_t m_start, vm_page_t m_end, |
| 2570 | u_long alignment, vm_paddr_t boundary, int options) |
| 2571 | { |
| 2572 | vm_object_t object; |
| 2573 | vm_paddr_t pa; |
| 2574 | vm_page_t m, m_run; |
| 2575 | #if VM_NRESERVLEVEL > 0 |
| 2576 | int level; |
| 2577 | #endif |
| 2578 | int m_inc, order, run_ext, run_len; |
| 2579 | |
| 2580 | KASSERT(npages > 0, ("npages is 0")); |
| 2581 | KASSERT(powerof2(alignment), ("alignment is not a power of 2")); |
| 2582 | KASSERT(powerof2(boundary), ("boundary is not a power of 2")); |
| 2583 | m_run = NULL; |
| 2584 | run_len = 0; |
| 2585 | for (m = m_start; m < m_end && run_len < npages; m += m_inc) { |
| 2586 | KASSERT((m->flags & PG_MARKER) == 0, |
| 2587 | ("page %p is PG_MARKER", m)); |
| 2588 | KASSERT((m->flags & PG_FICTITIOUS) == 0 || m->ref_count >= 1, |
| 2589 | ("fictitious page %p has invalid ref count", m)); |
| 2590 | |
| 2591 | /* |
| 2592 | * If the current page would be the start of a run, check its |
| 2593 | * physical address against the end, alignment, and boundary |
| 2594 | * conditions. If it doesn't satisfy these conditions, either |
| 2595 | * terminate the scan or advance to the next page that |
| 2596 | * satisfies the failed condition. |
| 2597 | */ |
| 2598 | if (run_len == 0) { |
| 2599 | KASSERT(m_run == NULL, ("m_run != NULL")); |
| 2600 | if (m + npages > m_end) |
| 2601 | break; |
| 2602 | pa = VM_PAGE_TO_PHYS(m); |
| 2603 | if ((pa & (alignment - 1)) != 0) { |
| 2604 | m_inc = atop(roundup2(pa, alignment) - pa); |
| 2605 | continue; |
| 2606 | } |
| 2607 | if (rounddown2(pa ^ (pa + ptoa(npages) - 1), |
| 2608 | boundary) != 0) { |
| 2609 | m_inc = atop(roundup2(pa, boundary) - pa); |
| 2610 | continue; |
| 2611 | } |
| 2612 | } else |
| 2613 | KASSERT(m_run != NULL, ("m_run == NULL")); |
| 2614 | |
| 2615 | retry: |
| 2616 | m_inc = 1; |
| 2617 | if (vm_page_wired(m)) |
| 2618 | run_ext = 0; |
| 2619 | #if VM_NRESERVLEVEL > 0 |
| 2620 | else if ((level = vm_reserv_level(m)) >= 0 && |
| 2621 | (options & VPSC_NORESERV) != 0) { |
| 2622 | run_ext = 0; |
| 2623 | /* Advance to the end of the reservation. */ |
| 2624 | pa = VM_PAGE_TO_PHYS(m); |
| 2625 | m_inc = atop(roundup2(pa + 1, vm_reserv_size(level)) - |
no test coverage detected