percpu变量初始化要点记录

pcpu_page_first_chunk函数先分配一块bootmem区间p,作为一级指针,然后为每个cpu分配n个页,依次把指针存放在p中。
p[0]..p[n-1]属于cpu0,p[n]-p[2n-1]属于cpu2,依次类推。

接着建立一个长度为n×NR_CPUS的虚拟空间(vmalloc_early),

并把虚拟空间对应的物理页框设置为p数组指向的pages。

然后把每cpu变量__per_cpu_load拷贝至这个虚拟空间。
最后计算偏移:
#define per_cpu(var, cpu) \
	(*SHIFT_PERCPU_PTR(&(var), per_cpu_offset(cpu)))
unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
for_each_possible_cpu(cpu)
		__per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu];
delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
其中pcpu_base_addr = base_addr; 这个base_addr就是之前分配的vm虚拟空间地址。
再来看这个pcpu_unit_offsets[cpu]是什么:
const unsigned long *pcpu_unit_offsets __read_mostly;
还是在函数pcpu_setup_first_chunk
pcpu_unit_offsets = unit_off;
unit_off = alloc_bootmem(nr_cpu_ids * sizeof(unit_off[0]));
unit_off[cpu] = gi->base_offset + i * ai->unit_size;
这个是分组的概念,不看也罢
第unit个单元,每个单元有unit_size这么大,即最终偏移为:
gi->base_offset = unit * ai->unit_size;

你可能感兴趣的:(每CPU变量)