How are percpu pointers implemented in the Linux kernel? -
on multiprocessor, each core can have own variables. thought different variables in different addresses, although in same process , have same name.
but wondering, how kernel implement this? dispense piece of memory deposit percpu pointers, , every time redirects pointer address shift or something?
normal global variables not per cpu. automatic variables on stack, , different cpus use different stack, naturally separate variables.
i guess you're referring linux's per-cpu variable infrastructure.
of magic here (asm-generic/percpu.h
):
extern unsigned long __per_cpu_offset[nr_cpus]; #define per_cpu_offset(x) (__per_cpu_offset[x]) /* separate out type, (int[3], foo) works. */ #define define_per_cpu(type, name) \ __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name /* var in discarded region: offset particular copy want */ #define per_cpu(var, cpu) (*reloc_hide(&per_cpu__##var, __per_cpu_offset[cpu])) #define __get_cpu_var(var) per_cpu(var, smp_processor_id())
the macro reloc_hide(ptr, offset)
advances ptr
given offset in bytes (regardless of pointer type).
what do?
- when defining
define_per_cpu(int, x)
, integer__per_cpu_x
created in special.data.percpu
section. - when kernel loaded, section loaded multiple times - once per cpu (this part of magic isn't in code above).
- the
__per_cpu_offset
array filled distances between copies. supposing 1000 bytes of per cpu data used,__per_cpu_offset[n]
contain1000*n
. - the symbol
per_cpu__x
relocated, during load, cpu 0'sper_cpu__x
. __get_cpu_var(x)
, when running on cpu 3, translate*reloc_hide(&per_cpu__x, __per_cpu_offset[3])
. starts cpu 0'sx
, adds offset between cpu 0's data , cpu 3's, , dereferences resulting pointer.
Comments
Post a Comment