Chapter3:MemoryManagement
The desired allocation size (x)isforwardedunchangedto__alloc_bootmem, but there are two options
for alignment in memory:SMP_CACHE_BYTESaligns the data on most architectures so that they are ideally
positioned in the L1 cache (despite its name the constant is, of course, also defined on uniprocessor
systems).PAGE_SIZEaligns the data on the page boundaries. The latter alignment is ideal for allocating
oneormorecompletepages,buttheformerproduces better results when parts of pages are allocated.
The distinction between low and normal memory is made by means of the start address. Searches for
DMA-suitable memory begins at the address 0, whereas requests for normal memory with RAM are
processed fromMAX_DMA_ADDRESSupward (__patranslates the memory address into a page number).
__alloc_bootmem_coreis a relatively extensive function (efficiency is not required during booting) that I
won’t discuss in detail as the main thing it does is to implement the first-fit algorithm already described.
However, the allocator has been enhanced to permitreservation not only of complete memory pages but
also smaller parts thereof.
The function performs the following (outline) actions:
- Starting atgoal, the page bitmap is scanned for a free area to satisfy the allocation request.
- If the page found immediately follows the last allocated page held inbootmem_data->
last_pos, the kernel checks by reference tobootmem_data->last_offsetwhether the
required memory (including the space needed to align the data) can be allocated in the last
page or can at least start there. - The bits of the newly allocated pages in the block bitmap are set to 1. The number of the last
page allocated is also stored inbootmem_data->last_pos. If the page is not fully allocated,
the appropriate offset is held inbootmem_data->last_offset; otherwise, this value is set
to 0.
Releasing Memory
The kernel provides thefree_bootmemfunction to free memory. It requires two parameters — the start
address and the size of the area to be freed. The name of the equivalent function on NUMA systems is
not surprisinglyfree_bootmem_node; it expects an additional parameter to define the appropriate node.
<bootmem.h>
void free_bootmem(unsigned long addr, unsigned long size);
void free_bootmem_node(pg_data_t *pgdat,
unsigned long addr,
unsigned long size);
Both versions delegate their work to__free_bootmem_core. Only whole pages can be freed because
the bootmem allocator does not keep any information about page divisions. The kernel uses
__free_bootmem_coreto first calculate the pages whose contents arefullyheld in the area to be freed.
Pages whose contents are only held in part in this area are ignored. The corresponding entries in the
page bitmap are set to 0 to conclude page freeing.
This procedure conceals the risk that a page is not freed if parts of its contents are returned in successive
requests. If the first half of a page and at some time later the second half of the same page are freed,
the allocator has no way of knowing that the entire page is no longer in use and can therefore be freed.
The page simply remains ‘‘in use,’’ although this is not the case. Nevertheless, this is not a big problem
becausefree_bootmemis very rarely used. Most memory areas allocated during system initialization are