Skip to content

Latest commit

 

History

History
110 lines (99 loc) · 5.89 KB

percpu.md

File metadata and controls

110 lines (99 loc) · 5.89 KB

Per-CPU

  • 对于给定处理器,Per-CPU的数据是唯一的。
  • 虽然访问 Per-CPU 数据不需要锁同步,但是禁止内核抢占还是需要的,防止出现伪并发。
  • get_cpu()put_cpu() 包含了对内核抢占的禁用和重新激活。
  • 2.6 Per-CPU 相关文件:
    • include/linux/percpu.h
    • arch/x86/include/asm/percpu.h
    • include/linux/percpu-defs.h
    • mm/slab.c
    • mm/percpu.c

编译时 Per-CPU 数据

  • 声明 Per-CPU 变量
    DECLARE_PER_CPU(type, name)
  • 定义 Per-CPU 变量
    DEFINE_PER_CPU(type, name)
  • get_cpu_var(var)put_cpu_var(var)per_cpu(name, cpu)
    #define per_cpu(var, cpu)   (*per_cpu_ptr(&(var), cpu))
    
    /*
     * Must be an lvalue. Since @var must be a simple identifier,
     * we force a syntax error here if it isn't.
     */
    #define get_cpu_var(var)                        \
    (*({                                    \
        preempt_disable();                      \
        this_cpu_ptr(&var);                     \
    }))
    
    /*
     * The weird & is necessary because sparse considers (void)(var) to be
     * a direct dereference of percpu variable (var).
     */
    #define put_cpu_var(var)                        \
    do {                                    \
        (void)&(var);                           \
        preempt_enable();                       \
    } while (0)
    ...'

注意

  • per_cpu(name, cpu)既不禁止抢占,也不提供锁保护。

    Another subtle note:These compile-time per-CPU examples do not work for modules because the linker actually creates them in a unique executable section (for the curious, .data.percpu ). If you need to access per-CPU data from modules, or if you need to create such data dynamically, there is hope.

运行时 Per-CPU 数据

  • 运行时创建和释放Per-CPU接口
    void *alloc_percpu(type); /* a macro */
    void *__alloc_percpu(size_t size, size_t align);
    void free_percpu(const void *);
  • __alignof__ 是gcc的一个功能,它返回指定类型或 lvalue 所需的(或建议的,要知道有些古怪的体系结构并没有字节对齐的要求) 对齐 字节数
    • 如果指定一个 lvalue,那么将返回 lvalue 的最大对齐字节数。
  • 使用运行时的 Per-CPU 数据
    get_cpu_var(ptr); /* return a void pointer to this processor’s copy of ptr */
    put_cpu_var(ptr); /* done; enable kernel preemption */

使用 Per-CPU 数据的原因

  • 减少数据锁定
    • 记住“只有这个处理器能访问这个数据”的规则是编程约定。
    • 并不存在措施禁止你从事欺骗活动。
    • 有越界的可能?
  • 大大减少缓存失效
    • 失效发生在处理器试图使它们的缓存保持同步时。
      • 如果一个处理器操作某个数据,而该数据又存放在其他处理器缓存中,那么存放该数据的那个处理器必须清理或刷新自己的缓存。
      • 持续不断的缓存失效称为 缓存抖动。这样对系统性能影响颇大。
    • 使用 Per-CPU 将使得缓存影响降至最低,因为理想情况下只会访问自己的数据。
    • percpu 接口 cache-align 所有数据,以便确保在访问一个处理器的数据时,不会将另一个处理器的数据带入同一个cache line上。
  • 注意:不能在访问 Per-CPU 数据过程中睡眠,否则,醒来可能在其他CPU上。
  • Per-CPU 的新接口并不兼容之前的内核。

Per-CPU 的原理

Per-CPU 的延申阅读