percpu相关-RELOC_HIDE(ptr, offset) ptr + offset 帮助函数
38 行定义 unsigned long 类型的 __ptr
39 行,将 输入 ptr 的值 放到 __ptr 里面。
40 行,__ptr 里面的值和 offset 的值相加。 但是返回的类型还是 ptr 的类型。
背景:
假设有对象类型
struct people
{
int age;
int height;
int weight;
}
对象大小是 sizeof struct people 大小为 3 * 4 = 12 字节。
假设: 一个people 对象指针 p,指向0x4000 0000
这时,你想要通过对 p 算数 加减得到 偏移 20 字节处的 struct people 对象,是不可能的。
因为,下一个people 对象的地址,肯定需要是 size of struct people 的整数倍。gcc 也以此来作优化。
p = p + 1; 这样会跳过 12个字节
p = p + 2;会跳过 24 个字节。
但是percpu 中,需要打破这个 整数倍 这个假设。所以搞这个 RELOC_HIDE(ptr, offset ) 这个helper。
它帮你偏移,返回偏移后的 对象指针。
为什么不将指针 强转为 long, 算数计算后,再强转为 struct people * ?
答: 可以这样搞。这个helper 就是这样搞的。你想要的也就是这个 helper。
include/linux/compiler-gcc.h
18/* 19 * This macro obfuscates arithmetic on a variable address so that gcc 20 * shouldn't recognize the original var, and make assumptions about it. 21 * 22 * This is needed because the C standard makes it undefined to do 23 * pointer arithmetic on "objects" outside their boundaries and the 24 * gcc optimizers assume this is the case. In particular they 25 * assume such arithmetic does not wrap. 26 * 27 * A miscompilation has been observed because of this on PPC. 28 * To work around it we hide the relationship of the pointer and the object 29 * using this macro. 30 * 31 * Versions of the ppc64 compiler before 4.1 had a bug where use of 32 * RELOC_HIDE could trash r30. The bug can be worked around by changing 33 * the inline assembly constraint from =g to =r, in this particular 34 * case either is valid. 35 */ 36#define RELOC_HIDE(ptr, off) \ 37({ \ 38 unsigned long __ptr; \ 39 __asm__ ("" : "=r"(__ptr) : "0"(ptr)); \ 40 (typeof(ptr)) (__ptr + (off)); \ 41}) 42