percpu之静态变量

Posted 天地有大美而不言

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了percpu之静态变量相关的知识,希望对你有一定的参考价值。

参考:Linux内核同步机制之(二):Per-CPU变量

    CPU私有变量(per-CPU变量)

    动态PCPU变量

setup_per_cpu_areas()初始化per-cpu数据。

static void __init setup_per_cpu_areas(void)
{
    unsigned long size, i;
    char *ptr;
    unsigned long nr_possible_cpus = num_possible_cpus();

    /* Copy section for each CPU (we discard the original) */
    size = ALIGN(PERCPU_ENOUGH_ROOM, PAGE_SIZE);
    ptr = alloc_bootmem_pages(size * nr_possible_cpus);

    for_each_possible_cpu(i) {
        __per_cpu_offset[i] = ptr - __per_cpu_start;
        memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
        ptr += size;
    }
}

下面的三个变量在vmlinux.lds中定义

        __per_cpu_load = .;
        __per_cpu_start = .;
            *(.data.percpu.page_aligned)
            *(.data.percpu)
            *(.data.percpu.shared_aligned)
        __per_cpu_end = .;

在init/main.c中定义如下变量

unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;

EXPORT_SYMBOL(__per_cpu_offset);

PERCPU_ENOUGH_ROOM是为每个cpu分配的副本空间大小,其中__per_cpu_end-__per_cpu_start为静态分配的percpu变量空间,

PERCPU_MODULE_RESERVE=8K位动态分配的percpu变量空间。

#define PERCPU_ENOUGH_ROOM                        \\
    ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) +  PERCPU_MODULE_RESERVE

#define PERCPU_MODULE_RESERVE        (8 << 10)

percpu变量静态声明

#define DEFINE_PER_CPU(type, name)         DEFINE_PER_CPU_SECTION(type, name, "")

#define DEFINE_PER_CPU_SECTION(type, name, section)            \\
    __attribute__((__section__(PER_CPU_BASE_SECTION section)))    \\
    PER_CPU_ATTRIBUTES PER_CPU_DEF_ATTRIBUTES            \\
    __typeof__(type) per_cpu__##name

#define PER_CPU_BASE_SECTION ".data.percpu"

由于静态变量的特殊性,没有头文件声明percpu变量,用DEFINE_PER_CPU宏定义的变量想在其它C文件中使用,需要使用DECLARE_PER_CPU宏声明

#define DECLARE_PER_CPU(type, name)                    \\
    DECLARE_PER_CPU_SECTION(type, name, "")

#define DECLARE_PER_CPU_SECTION(type, name, section)            \\
    extern                                \\
    __attribute__((__section__(PER_CPU_BASE_SECTION section)))    \\
    PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name

使用per_cpu宏获取静态存储的percpu变量

#define per_cpu(var, cpu) \\
    (*SHIFT_PERCPU_PTR(&per_cpu_var(var), per_cpu_offset(cpu)))     
     
#define per_cpu_offset(x) (__per_cpu_offset[x])
#define per_cpu_var(var) per_cpu__##var
#define SHIFT_PERCPU_PTR(__p, __offset)    RELOC_HIDE((__p), (__offset))

#define RELOC_HIDE(ptr, off)                    \\
  ({ unsigned long __ptr;                    \\
    __asm__ ("" : "=r"(__ptr) : "0"(ptr));        \\
    (typeof(ptr)) (__ptr + (off)); })

 

以上是关于percpu之静态变量的主要内容,如果未能解决你的问题,请参考以下文章

内核源码解读之内存管理(10)percpu_page_set分析

Java 核心基础之static静态代码块和静态方法

如何更改片段中的主要活动变量

支持动态或静态片段的不同屏幕尺寸?

从外部存储中检索 Relay 查询片段的变量

Java基础总结之Thymeleaf详解