Chapter3:MemoryManagement
If the lazy coalescing limit is not exceeded, the page is simply kept on the per-CPU cache. However, it
is important that theprivateelement be set to the migrate type of the page. As described, this allows
allocations fulfilled from the per-CPU cache to pick only pages of the proper migrate type.
If more than one page is freed, then__free_pagesdelegates work (after a detour that is not interesting
for our purposes) tofree_pages_okand finally tofree_one_page. Despite the name, the function
not only handles freeing of single pages, but also takes compound pages into account.
mm/page_alloc.c
static inline void __free_one_page (struct page *page,
struct zone *zone, unsigned int order)
This function is the cornerstone of memory freeing. The relevant area is added to the appropriate
free_arealist of the buddy system. When buddy pairs arefreed, the function coalesces them into a
contiguous area that is then placed in the next higherfree_arealist. If this reunites a further buddy
pair, it is also coalesced and moved to a higher list. This procedure is repeated until all possible buddy
pairs have been coalesced and the changes have been propagated upward as far as possible.
However, this doesn’t answer the question as to how the kernel knows that both parts of a buddy pair
are located on the list of free pages. To place a page group back into the buddy system, the kernel must
be able to compute two things: the address of the potential buddy and the index of the combined page
group if both buddies can be recombined. Two auxiliary functions are provided for this purpose:
mm/page_alloc.c
static inline struct page *
__page_find_buddy(struct page *page, unsigned long page_idx, unsigned int order)
{
unsigned long buddy_idx = page_idx ^ (1 << order);
return page + (buddy_idx - page_idx);
}
static inline unsigned long
__find_combined_index(unsigned long page_idx, unsigned int order)
{
return (page_idx & ~(1 << order));
}
It is advantageous to remember that the operator^performs a bitwise XOR operation. The calculations
performed by the function will be clarified by an example immediately.
First, we need to introduce one more helper function, though. The page index of the buddy is not enough.
The kernel must also ensure that all pages, belonging to the buddy are free and thus contained in the
buddy system to be able to merge both pairs:
mm/page_alloc.c
static inline int page_is_buddy(struct page *page, struct page *buddy,
int order)
{