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

 

posted @ 2022-03-25 11:34  张志伟122  阅读(249)  评论(0编辑  收藏  举报