numa_node_id是得到当前cpu对应的numa id

来源:互联网 发布:架子鼓软件 编辑:程序博客网 时间:2024/06/06 19:39
在定义CONFIG_USE_PERCPU_NUMA_NODE_ID的时候可以通过static inline int numa_node_id(void){return raw_cpu_read(numa_node);}得到当前cpu的numa id注意这里的numa_node 是一个per_cpu 变量,其定义如下:DECLARE_PER_CPU(int, numa_node);例如实际code中通过下面的方式拿到当前cpu的numa idif (node < 0)node = numa_node_id();下来看看为啥raw_cpu_read等得到当前cpu的numa id#define raw_cpu_read(pcp)__pcpu_size_call_return(raw_cpu_read_, pcp)继续看看__pcpu_size_call_return#define __pcpu_size_call_return(stem, variable)\({\typeof(variable) pscr_ret__;\__verify_pcpu_ptr(&(variable));\switch(sizeof(variable)) {\case 1: pscr_ret__ = stem##1(variable); break;\case 2: pscr_ret__ = stem##2(variable); break;\case 4: pscr_ret__ = stem##4(variable); break;\case 8: pscr_ret__ = stem##8(variable); break;\default:\__bad_size_call_parameter(); break;\}\pscr_ret__;\})这里做完替换后就是raw_cpu_read_4(numa_node)#ifndef raw_cpu_read_4#define raw_cpu_read_4(pcp)raw_cpu_generic_read(pcp)#endif继续看raw_cpu_generic_read#define raw_cpu_generic_read(pcp)\({\*raw_cpu_ptr(&(pcp));\})继续看#define raw_cpu_ptr(ptr)\({\__verify_pcpu_ptr(ptr);\arch_raw_cpu_ptr(ptr);\})这里的核心是arch_raw_cpu_ptr#ifndef arch_raw_cpu_ptr#define arch_raw_cpu_ptr(ptr) SHIFT_PERCPU_PTR(ptr, __my_cpu_offset)#endif这里的ptr就是numa_node,因此通过__my_cpu_offset得到当前cpu在numa_node中的offset,就可以得到当前cpu的idstatic inline unsigned long __my_cpu_offset(void){unsigned long off;/* * We want to allow caching the value, so avoid using volatile and * instead use a fake stack read to hazard against barrier(). */asm("mrs %0, tpidr_el1" : "=r" (off) :"Q" (*(const unsigned long *)current_stack_pointer));return off;}#define __my_cpu_offset __my_cpu_offset()这里的通过__my_cpu_offset得到每个cpu对应的offset。与之对应的是每个cpu的boot的过程中都会调用set_my_cpu_offset来在numa_node中设置offset。例如这了是cpu 0的void __init smp_setup_processor_id(void){u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;cpu_logical_map(0) = mpidr;/* * clear __my_cpu_offset on boot CPU to avoid hang caused by * using percpu variable early, for example, lockdep will * access percpu variable inside lock_release */set_my_cpu_offset(0);pr_info("Booting Linux on physical CPU 0x%lx\n", (unsigned long)mpidr);}下面其其他cpu的asmlinkage void secondary_start_kernel(void){struct mm_struct *mm = &init_mm;unsigned int cpu;cpu = task_cpu(current);set_my_cpu_offset(per_cpu_offset(cpu));}