Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_phys.c
Show First 20 Lines • Show All 599 Lines • ▼ Show 20 Lines | while (oind > order) { | ||||
KASSERT(m_buddy->order == VM_NFREEORDER, | KASSERT(m_buddy->order == VM_NFREEORDER, | ||||
("vm_phys_split_pages: page %p has unexpected order %d", | ("vm_phys_split_pages: page %p has unexpected order %d", | ||||
m_buddy, m_buddy->order)); | m_buddy, m_buddy->order)); | ||||
vm_freelist_add(fl, m_buddy, oind, 0); | vm_freelist_add(fl, m_buddy, oind, 0); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* 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 allocate the desired number of pages will avoid | |||||
* wasted time in vm_phys_split_pages(). | |||||
* | |||||
* The free page queues for the specified domain must be locked. | |||||
*/ | |||||
int | |||||
vm_phys_alloc_npages(int domain, int pool, int npages, vm_page_t ma[]) | |||||
{ | |||||
struct vm_freelist *alt, *fl; | |||||
vm_page_t m; | |||||
int avail, end, flind, freelist, i, need, oind, pind; | |||||
KASSERT(domain >= 0 && domain < vm_ndomains, | |||||
("vm_phys_alloc_npages: domain %d is out of range", domain)); | |||||
KASSERT(pool < VM_NFREEPOOL, | |||||
("vm_phys_alloc_npages: pool %d is out of range", pool)); | |||||
KASSERT(npages <= 1 << (VM_NFREEORDER - 1), | |||||
("vm_phys_alloc_npages: npages %d is out of range", npages)); | |||||
vm_domain_free_assert_locked(VM_DOMAIN(domain)); | |||||
i = 0; | |||||
for (freelist = 0; freelist < VM_NFREELIST; freelist++) { | |||||
flind = vm_freelist_to_flind[freelist]; | |||||
if (flind < 0) | |||||
continue; | |||||
fl = vm_phys_free_queues[domain][flind][pool]; | |||||
for (oind = 0; oind < VM_NFREEORDER; oind++) { | |||||
while ((m = TAILQ_FIRST(&fl[oind].pl)) != NULL) { | |||||
vm_freelist_rem(fl, m, oind); | |||||
avail = 1 << oind; | |||||
need = imin(npages - i, avail); | |||||
for (end = i + need; i < end;) | |||||
ma[i++] = m++; | |||||
if (need < avail) { | |||||
vm_phys_free_contig(m, avail - need); | |||||
return (npages); | |||||
} else if (i == npages) | |||||
return (npages); | |||||
} | |||||
} | |||||
for (oind = VM_NFREEORDER - 1; oind >= 0; oind--) { | |||||
for (pind = 0; pind < VM_NFREEPOOL; pind++) { | |||||
alt = vm_phys_free_queues[domain][flind][pind]; | |||||
while ((m = TAILQ_FIRST(&alt[oind].pl)) != | |||||
NULL) { | |||||
vm_freelist_rem(alt, m, oind); | |||||
vm_phys_set_pool(pool, m, oind); | |||||
avail = 1 << oind; | |||||
need = imin(npages - i, avail); | |||||
for (end = i + need; i < end;) | |||||
ma[i++] = m++; | |||||
if (need < avail) { | |||||
vm_phys_free_contig(m, avail - | |||||
need); | |||||
return (npages); | |||||
} else if (i == npages) | |||||
return (npages); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
return (i); | |||||
} | |||||
/* | |||||
* Allocate a contiguous, power of two-sized set of physical pages | * Allocate a contiguous, power of two-sized set of physical pages | ||||
* from the free lists. | * from the free lists. | ||||
* | * | ||||
* The free page queues must be locked. | * The free page queues must be locked. | ||||
*/ | */ | ||||
vm_page_t | vm_page_t | ||||
vm_phys_alloc_pages(int domain, int pool, int order) | vm_phys_alloc_pages(int domain, int pool, int order) | ||||
{ | { | ||||
vm_page_t m; | vm_page_t m; | ||||
int freelist; | int freelist; | ||||
for (freelist = 0; freelist < VM_NFREELIST; freelist++) { | for (freelist = 0; freelist < VM_NFREELIST; freelist++) { | ||||
m = vm_phys_alloc_freelist_pages(domain, freelist, pool, order); | m = vm_phys_alloc_freelist_pages(domain, freelist, pool, order); | ||||
if (m != NULL) | if (m != NULL) | ||||
return (m); | return (m); | ||||
} | } | ||||
return (NULL); | return (NULL); | ||||
} | |||||
int | |||||
vm_phys_alloc_npages(int domain, int pool, vm_page_t *mp, int cnt) | |||||
{ | |||||
vm_page_t m; | |||||
int order, freelist; | |||||
for (freelist = 0; freelist < VM_NFREELIST; freelist++) { | |||||
for (order = fls(cnt) -1; order >= 0; order--) { | |||||
m = vm_phys_alloc_freelist_pages(domain, freelist, | |||||
pool, order); | |||||
if (m != NULL) { | |||||
*mp = m; | |||||
return (1 << order); | |||||
} | |||||
} | |||||
} | |||||
*mp = NULL; | |||||
return (0); | |||||
} | } | ||||
/* | /* | ||||
* Allocate a contiguous, power of two-sized set of physical pages from the | * Allocate a contiguous, power of two-sized set of physical pages from the | ||||
* specified free list. The free list must be specified using one of the | * specified free list. The free list must be specified using one of the | ||||
* manifest constants VM_FREELIST_*. | * manifest constants VM_FREELIST_*. | ||||
* | * | ||||
* The free page queues must be locked. | * The free page queues must be locked. | ||||
▲ Show 20 Lines • Show All 646 Lines • Show Last 20 Lines |