内核的bootmem 分配器 又叫自举内存分配器,其内涵即 自己初始化自己的一个内存分配器
其初始化过程 已在 上篇[ARM 架构物理内存初始化],(https://blog.csdn.net/zsj1126/article/details/116430903)介绍
本文主要关注该分配器提供的主要接口和用途
static void * __init __alloc_bootmem_core (bootmem_data_t *bdata,
unsigned long size, unsigned long align, unsigned long goal)
bdata, 指向node的bootmem分配器j结构
size : 申请空间字节数
align: 申请地址对齐大小
goal: 目标起始位置
offset = 0;
if (align &&
(bdata->node_boot_start & (align - 1UL)) != 0)
offset = (align - (bdata->node_boot_start & (align - 1UL)));
offset >>= PAGE_SHIFT;
/*
* We try to allocate bootmem pages above 'goal'
* first, then we try to allocate lower pages.
*/
if (goal && (goal >= bdata->node_boot_start) &&
((goal >> PAGE_SHIFT) < bdata->node_low_pfn)) {
preferred = goal - bdata->node_boot_start;
} else
preferred = 0;
preferred = ((preferred + align - 1) & ~(align - 1)) >> PAGE_SHIFT;
preferred += offset;
areasize = (size+PAGE_SIZE-1)/PAGE_SIZE;
incr = align >> PAGE_SHIFT ? : 1; // 步进对齐
以页为单位分配,起始地址对齐和计算,如goal 非0 ,则从goal 开始扫描。
restart_scan:
for (i = preferred; i < eidx; i += incr) {
unsigned long j;
if (test_bit(i, bdata->node_bootmem_map))
continue;
for (j = i + 1; j < i + areasize; ++j) {
if (j >= eidx)
goto fail_block;
if (test_bit (j, bdata->node_bootmem_map))
goto fail_block;
}
start = i;
goto found;
fail_block:;
}
if (preferred) {
preferred = offset;
goto restart_scan;
}
return NULL;
扫描map, 找到合适位置,如有指定地址,未扫到,还需从头再扫
209-210 : 判断是否可以合并分配
last_pos: 上次分配的bootmem页结束id
last_offset: 上次分配的bootmem页内偏移
238-239:分配标志标记