Changeset View
Standalone View
vm_phys.c
Show First 20 Lines • Show All 1,089 Lines • ▼ Show 20 Lines | do { | ||||
m = &seg->first_page[atop(pa - seg->start)]; | m = &seg->first_page[atop(pa - seg->start)]; | ||||
} while (order < VM_NFREEORDER - 1); | } while (order < VM_NFREEORDER - 1); | ||||
} | } | ||||
fl = (*seg->free_queues)[m->pool]; | fl = (*seg->free_queues)[m->pool]; | ||||
vm_freelist_add(fl, m, order, 1); | vm_freelist_add(fl, m, order, 1); | ||||
} | } | ||||
/* | /* | ||||
* Free a contiguous, arbitrarily sized set of physical pages. | * Return the largest possible order of a set of pages starting at m. | ||||
*/ | |||||
static int | |||||
max_order(vm_page_t m) | |||||
{ | |||||
alc: For the time being, style(9) still requires a blank line here. (There is a proposal to… | |||||
/* | |||||
* Unsigned "min" is used here so that "order" is assigned | |||||
* "VM_NFREEORDER - 1" when "m"'s physical address is zero | |||||
* or the low-order bits of its physical address are zero | |||||
* because the size of a physical address exceeds the size of | |||||
* a long. | |||||
*/ | |||||
return (min(ffsl(VM_PAGE_TO_PHYS(m) >> PAGE_SHIFT) - 1, | |||||
VM_NFREEORDER - 1)); | |||||
} | |||||
/* | |||||
* Free a contiguous, arbitrarily sized set of physical pages, without | |||||
* merging across set boundaries. | |||||
Done Inline Actions"... of a set of pages starting ..." alc: "... of a set of pages starting ..." | |||||
* | * | ||||
* The free page queues must be locked. | * The free page queues must be locked. | ||||
*/ | */ | ||||
Done Inline Actions"... must be superpage boundary, ...". No. I think that you are trying to explain why vm_reserv_break() can call this function. Reservations are provided by the buddy allocator, and thus they are aligned on an address that is a multiple of their size. When we are breaking a reservation, there is at least one allocated page within the reservation. The pages being freed by vm_reserv_break() can't possibly coalesce with a page from outside the reservation until those pages are freed. alc: "... must be superpage boundary, ...". No. I think that you are trying to explain why… | |||||
Done Inline ActionsParagraph deleted. dougm: Paragraph deleted. | |||||
void | void | ||||
vm_phys_free_contig(vm_page_t m, u_long npages) | vm_phys_enqueue_contig(vm_page_t m, u_long npages) | ||||
Done Inline ActionsI suggest vm_phys_enqueue_contig(). alc: I suggest vm_phys_enqueue_contig(). | |||||
{ | { | ||||
u_int n; | struct vm_freelist *fl; | ||||
struct vm_phys_seg *seg; | |||||
vm_page_t m_end; | |||||
int order; | int order; | ||||
/* | /* | ||||
* Avoid unnecessary coalescing by freeing the pages in the largest | * Avoid unnecessary coalescing by freeing the pages in the largest | ||||
* possible power-of-two-sized subsets. | * possible power-of-two-sized subsets. | ||||
*/ | */ | ||||
vm_domain_free_assert_locked(vm_pagequeue_domain(m)); | vm_domain_free_assert_locked(vm_pagequeue_domain(m)); | ||||
for (;; npages -= n) { | seg = &vm_phys_segs[m->segind]; | ||||
/* | fl = (*seg->free_queues)[m->pool]; | ||||
* Unsigned "min" is used here so that "order" is assigned | m_end = m + npages; | ||||
* "VM_NFREEORDER - 1" when "m"'s physical address is zero | /* Free blocks of increasing size. */ | ||||
* or the low-order bits of its physical address are zero | while ((order = max_order(m)) < VM_NFREEORDER - 1 && | ||||
* because the size of a physical address exceeds the size of | m + (1 << order) <= m_end) { | ||||
* a long. | KASSERT(seg == &vm_phys_segs[m->segind], | ||||
*/ | ("%s: page range [%p,%p) spans multiple segments", | ||||
order = min(ffsl(VM_PAGE_TO_PHYS(m) >> PAGE_SHIFT) - 1, | __func__, m_end - npages, m)); | ||||
Done Inline ActionsThe page range that spans two segments is [original "m", current "m"), not [current "m", "m_end"). alc: The page range that spans two segments is [original "m", current "m"), not [current "m"… | |||||
Done Inline Actionsoriginal "m" == m_end - npages. dougm: original "m" == m_end - npages. | |||||
Done Inline ActionsDeindent this line by one space. alc: Deindent this line by one space. | |||||
VM_NFREEORDER - 1); | vm_freelist_add(fl, m, order, 1); | ||||
n = 1 << order; | m += 1 << order; | ||||
Done Inline ActionsUnnecessary parentheses. alc: Unnecessary parentheses. | |||||
if (npages < n) | |||||
break; | |||||
vm_phys_free_pages(m, order); | |||||
m += n; | |||||
} | } | ||||
/* The residual "npages" is less than "1 << (VM_NFREEORDER - 1)". */ | /* Free blocks of maximum size. */ | ||||
for (; npages > 0; npages -= n) { | while (m + (1 << order) <= m_end) { | ||||
order = flsl(npages) - 1; | KASSERT(seg == &vm_phys_segs[m->segind], | ||||
n = 1 << order; | ("%s: page range [%p,%p) spans multiple segments", | ||||
vm_phys_free_pages(m, order); | __func__, m_end - npages, m)); | ||||
Done Inline ActionsDeindent this line by one space. alc: Deindent this line by one space. | |||||
m += n; | vm_freelist_add(fl, m, order, 1); | ||||
m += 1 << order; | |||||
Done Inline ActionsUnnecessary parentheses. alc: Unnecessary parentheses. | |||||
} | } | ||||
/* Free blocks of diminishing size. */ | |||||
while (m < m_end) { | |||||
KASSERT(seg == &vm_phys_segs[m->segind], | |||||
("%s: page range [%p,%p) spans multiple segments", | |||||
__func__, m_end - npages, m)); | |||||
Done Inline ActionsDeindent this line by one space. alc: Deindent this line by one space. | |||||
order = flsl(m_end - m) - 1; | |||||
vm_freelist_add(fl, m, order, 1); | |||||
m += 1 << order; | |||||
Done Inline ActionsUnnecessary parentheses. alc: Unnecessary parentheses. | |||||
} | |||||
} | |||||
/* | |||||
* Free a contiguous, arbitrarily sized set of physical pages. | |||||
* | |||||
* The free page queues must be locked. | |||||
*/ | |||||
void | |||||
vm_phys_free_contig(vm_page_t m, u_long npages) | |||||
{ | |||||
int order_start, order_end; | |||||
vm_page_t m_start, m_end; | |||||
vm_domain_free_assert_locked(vm_pagequeue_domain(m)); | |||||
m_start = m; | |||||
order_start = max_order(m_start); | |||||
if (order_start < VM_NFREEORDER - 1) | |||||
m_start += 1 << order_start; | |||||
m_end = m + npages; | |||||
order_end = max_order(m_end); | |||||
if (order_end < VM_NFREEORDER - 1) | |||||
m_end -= 1 << order_end; | |||||
/* | |||||
* Avoid unnecessary coalescing by freeing the pages at the start and | |||||
* end of the range last. | |||||
*/ | |||||
if (m_start < m_end) | |||||
vm_phys_enqueue_contig(m_start, m_end - m_start); | |||||
if (order_start < VM_NFREEORDER - 1) | |||||
vm_phys_free_pages(m, order_start); | |||||
if (order_end < VM_NFREEORDER - 1) | |||||
vm_phys_free_pages(m_end, order_end); | |||||
} | } | ||||
/* | /* | ||||
* Scan physical memory between the specified addresses "low" and "high" for a | * Scan physical memory between the specified addresses "low" and "high" for a | ||||
* run of contiguous physical pages that satisfy the specified conditions, and | * run of contiguous physical pages that satisfy the specified conditions, and | ||||
* return the lowest page in the run. The specified "alignment" determines | * return the lowest page in the run. The specified "alignment" determines | ||||
* the alignment of the lowest physical page in the run. If the specified | * the alignment of the lowest physical page in the run. If the specified | ||||
* "boundary" is non-zero, then the run of physical pages cannot span a | * "boundary" is non-zero, then the run of physical pages cannot span a | ||||
▲ Show 20 Lines • Show All 298 Lines • Show Last 20 Lines |
For the time being, style(9) still requires a blank line here. (There is a proposal to eliminate that rule that might apply here.)