* Tries to allocate the specified number of pages from the specified pool * within the specified domain. Returns the actual number of allocated pages * and a pointer to each page through the array ma[]. * * The returned pages may not be physically contiguous. However, in contrast * to performing multiple, back-to-back calls to vm_phys_alloc_pages(..., 0), * calling this function once to al
| 724 | * The free page queues for the specified domain must be locked. |
| 725 | */ |
| 726 | int |
| 727 | vm_phys_alloc_npages(int domain, int pool, int npages, vm_page_t ma[]) |
| 728 | { |
| 729 | struct vm_freelist *alt, *fl; |
| 730 | vm_page_t m; |
| 731 | int avail, end, flind, freelist, i, need, oind, pind; |
| 732 | |
| 733 | KASSERT(domain >= 0 && domain < vm_ndomains, |
| 734 | ("vm_phys_alloc_npages: domain %d is out of range", domain)); |
| 735 | KASSERT(pool < VM_NFREEPOOL, |
| 736 | ("vm_phys_alloc_npages: pool %d is out of range", pool)); |
| 737 | KASSERT(npages <= 1 << (VM_NFREEORDER - 1), |
| 738 | ("vm_phys_alloc_npages: npages %d is out of range", npages)); |
| 739 | vm_domain_free_assert_locked(VM_DOMAIN(domain)); |
| 740 | i = 0; |
| 741 | for (freelist = 0; freelist < VM_NFREELIST; freelist++) { |
| 742 | flind = vm_freelist_to_flind[freelist]; |
| 743 | if (flind < 0) |
| 744 | continue; |
| 745 | fl = vm_phys_free_queues[domain][flind][pool]; |
| 746 | for (oind = 0; oind < VM_NFREEORDER; oind++) { |
| 747 | while ((m = TAILQ_FIRST(&fl[oind].pl)) != NULL) { |
| 748 | vm_freelist_rem(fl, m, oind); |
| 749 | avail = 1 << oind; |
| 750 | need = imin(npages - i, avail); |
| 751 | for (end = i + need; i < end;) |
| 752 | ma[i++] = m++; |
| 753 | if (need < avail) { |
| 754 | /* |
| 755 | * Return excess pages to fl. Its |
| 756 | * order [0, oind) queues are empty. |
| 757 | */ |
| 758 | vm_phys_enq_range(m, avail - need, fl, |
| 759 | 1); |
| 760 | return (npages); |
| 761 | } else if (i == npages) |
| 762 | return (npages); |
| 763 | } |
| 764 | } |
| 765 | for (oind = VM_NFREEORDER - 1; oind >= 0; oind--) { |
| 766 | for (pind = 0; pind < VM_NFREEPOOL; pind++) { |
| 767 | alt = vm_phys_free_queues[domain][flind][pind]; |
| 768 | while ((m = TAILQ_FIRST(&alt[oind].pl)) != |
| 769 | NULL) { |
| 770 | vm_freelist_rem(alt, m, oind); |
| 771 | vm_phys_set_pool(pool, m, oind); |
| 772 | avail = 1 << oind; |
| 773 | need = imin(npages - i, avail); |
| 774 | for (end = i + need; i < end;) |
| 775 | ma[i++] = m++; |
| 776 | if (need < avail) { |
| 777 | /* |
| 778 | * Return excess pages to fl. |
| 779 | * Its order [0, oind) queues |
| 780 | * are empty. |
| 781 | */ |
| 782 | vm_phys_enq_range(m, avail - |
| 783 | need, fl, 1); |
no test coverage detected